xref: /trunk/main/oox/source/helper/attributelist.cxx (revision 9621e552)
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 #include "oox/helper/attributelist.hxx"
25 #include "oox/helper/datetimehelper.hxx"
26 
27 #include <osl/diagnose.h>
28 #include <rtl/ustrbuf.hxx>
29 #include "oox/token/tokenmap.hxx"
30 
31 namespace oox {
32 
33 // ============================================================================
34 
35 using namespace ::com::sun::star::uno;
36 using namespace ::com::sun::star::util;
37 using namespace ::com::sun::star::xml::sax;
38 
39 using ::rtl::OUString;
40 using ::rtl::OUStringBuffer;
41 
42 // ============================================================================
43 
44 namespace {
45 
46 const sal_Int32 XSTRING_ENCCHAR_LEN     = 7;
47 
lclAddHexDigit(sal_Unicode & orcChar,sal_Unicode cDigit,int nBitShift)48 bool lclAddHexDigit( sal_Unicode& orcChar, sal_Unicode cDigit, int nBitShift )
49 {
50     if( ('0' <= cDigit) && (cDigit <= '9') ) { orcChar |= ((cDigit - '0') << nBitShift); return true; }
51     if( ('a' <= cDigit) && (cDigit <= 'f') ) { orcChar |= ((cDigit - 'a' + 10) << nBitShift); return true; }
52     if( ('A' <= cDigit) && (cDigit <= 'F') ) { orcChar |= ((cDigit - 'A' + 10) << nBitShift); return true; }
53     return false;
54 }
55 
lclGetXChar(const sal_Unicode * & rpcStr,const sal_Unicode * pcEnd)56 sal_Unicode lclGetXChar( const sal_Unicode*& rpcStr, const sal_Unicode* pcEnd )
57 {
58     sal_Unicode cChar = 0;
59     if( (pcEnd - rpcStr >= XSTRING_ENCCHAR_LEN) &&
60         (rpcStr[ 0 ] == '_') &&
61         (rpcStr[ 1 ] == 'x') &&
62         (rpcStr[ 6 ] == '_') &&
63         lclAddHexDigit( cChar, rpcStr[ 2 ], 12 ) &&
64         lclAddHexDigit( cChar, rpcStr[ 3 ], 8 ) &&
65         lclAddHexDigit( cChar, rpcStr[ 4 ], 4 ) &&
66         lclAddHexDigit( cChar, rpcStr[ 5 ], 0 ) )
67     {
68         rpcStr += XSTRING_ENCCHAR_LEN;
69         return cChar;
70     }
71     return *rpcStr++;
72 }
73 
74 } // namespace
75 
76 // ----------------------------------------------------------------------------
77 
decodeToken(const OUString & rValue)78 sal_Int32 AttributeConversion::decodeToken( const OUString& rValue )
79 {
80     return StaticTokenMap::get().getTokenFromUnicode( rValue );
81 }
82 
decodeXString(const OUString & rValue)83 OUString AttributeConversion::decodeXString( const OUString& rValue )
84 {
85     // string shorter than one encoded character - no need to decode
86     if( rValue.getLength() < XSTRING_ENCCHAR_LEN )
87         return rValue;
88     OUStringBuffer aBuffer;
89     const sal_Unicode* pcStr = rValue.getStr();
90     const sal_Unicode* pcEnd = pcStr + rValue.getLength();
91     while( pcStr < pcEnd )
92         aBuffer.append( lclGetXChar( pcStr, pcEnd ) );
93     return aBuffer.makeStringAndClear();
94 }
95 
decodeDouble(const OUString & rValue)96 double AttributeConversion::decodeDouble( const OUString& rValue )
97 {
98     return rValue.toDouble();
99 }
100 
decodeInteger(const OUString & rValue)101 sal_Int32 AttributeConversion::decodeInteger( const OUString& rValue )
102 {
103     return rValue.toInt32();
104 }
105 
decodeUnsigned(const OUString & rValue)106 sal_uInt32 AttributeConversion::decodeUnsigned( const OUString& rValue )
107 {
108     return getLimitedValue< sal_uInt32, sal_Int64 >( rValue.toInt64(), 0, SAL_MAX_UINT32 );
109 }
110 
decodeHyper(const OUString & rValue)111 sal_Int64 AttributeConversion::decodeHyper( const OUString& rValue )
112 {
113     return rValue.toInt64();
114 }
115 
decodeIntegerHex(const OUString & rValue)116 sal_Int32 AttributeConversion::decodeIntegerHex( const OUString& rValue )
117 {
118     return rValue.toInt32( 16 );
119 }
120 
decodeUnsignedHex(const OUString & rValue)121 sal_uInt32 AttributeConversion::decodeUnsignedHex( const OUString& rValue )
122 {
123     return getLimitedValue< sal_uInt32, sal_Int64 >( rValue.toInt64( 16 ), 0, SAL_MAX_UINT32 );
124 }
125 
decodeHyperHex(const OUString & rValue)126 sal_Int64 AttributeConversion::decodeHyperHex( const OUString& rValue )
127 {
128     return rValue.toInt64( 16 );
129 }
130 
131 // ============================================================================
132 
AttributeList(const Reference<XFastAttributeList> & rxAttribs)133 AttributeList::AttributeList( const Reference< XFastAttributeList >& rxAttribs ) :
134     mxAttribs( rxAttribs )
135 {
136     OSL_ENSURE( mxAttribs.is(), "AttributeList::AttributeList - missing attribute list interface" );
137 }
138 
hasAttribute(sal_Int32 nAttrToken) const139 bool AttributeList::hasAttribute( sal_Int32 nAttrToken ) const
140 {
141     return mxAttribs->hasAttribute( nAttrToken );
142 }
143 
144 // optional return values -----------------------------------------------------
145 
getToken(sal_Int32 nAttrToken) const146 OptValue< sal_Int32 > AttributeList::getToken( sal_Int32 nAttrToken ) const
147 {
148     sal_Int32 nToken = mxAttribs->getOptionalValueToken( nAttrToken, XML_TOKEN_INVALID );
149     return OptValue< sal_Int32 >( nToken != XML_TOKEN_INVALID, nToken );
150 }
151 
getString(sal_Int32 nAttrToken) const152 OptValue< OUString > AttributeList::getString( sal_Int32 nAttrToken ) const
153 {
154     // check if the attribute exists (empty string may be different to missing attribute)
155     if( mxAttribs->hasAttribute( nAttrToken ) )
156         return OptValue< OUString >( mxAttribs->getOptionalValue( nAttrToken ) );
157     return OptValue< OUString >();
158 }
159 
getXString(sal_Int32 nAttrToken) const160 OptValue< OUString > AttributeList::getXString( sal_Int32 nAttrToken ) const
161 {
162     // check if the attribute exists (empty string may be different to missing attribute)
163     if( mxAttribs->hasAttribute( nAttrToken ) )
164         return OptValue< OUString >( AttributeConversion::decodeXString( mxAttribs->getOptionalValue( nAttrToken ) ) );
165     return OptValue< OUString >();
166 }
167 
getDouble(sal_Int32 nAttrToken) const168 OptValue< double > AttributeList::getDouble( sal_Int32 nAttrToken ) const
169 {
170     OUString aValue = mxAttribs->getOptionalValue( nAttrToken );
171     bool bValid = aValue.getLength() > 0;
172     return OptValue< double >( bValid, bValid ? AttributeConversion::decodeDouble( aValue ) : 0.0 );
173 }
174 
getInteger(sal_Int32 nAttrToken) const175 OptValue< sal_Int32 > AttributeList::getInteger( sal_Int32 nAttrToken ) const
176 {
177     OUString aValue = mxAttribs->getOptionalValue( nAttrToken );
178     bool bValid = aValue.getLength() > 0;
179     return OptValue< sal_Int32 >( bValid, bValid ? AttributeConversion::decodeInteger( aValue ) : 0 );
180 }
181 
getUnsigned(sal_Int32 nAttrToken) const182 OptValue< sal_uInt32 > AttributeList::getUnsigned( sal_Int32 nAttrToken ) const
183 {
184     OUString aValue = mxAttribs->getOptionalValue( nAttrToken );
185     bool bValid = aValue.getLength() > 0;
186     return OptValue< sal_uInt32 >( bValid, AttributeConversion::decodeUnsigned( aValue ) );
187 }
188 
getHyper(sal_Int32 nAttrToken) const189 OptValue< sal_Int64 > AttributeList::getHyper( sal_Int32 nAttrToken ) const
190 {
191     OUString aValue = mxAttribs->getOptionalValue( nAttrToken );
192     bool bValid = aValue.getLength() > 0;
193     return OptValue< sal_Int64 >( bValid, bValid ? AttributeConversion::decodeHyper( aValue ) : 0 );
194 }
195 
getIntegerHex(sal_Int32 nAttrToken) const196 OptValue< sal_Int32 > AttributeList::getIntegerHex( sal_Int32 nAttrToken ) const
197 {
198     OUString aValue = mxAttribs->getOptionalValue( nAttrToken );
199     bool bValid = aValue.getLength() > 0;
200     return OptValue< sal_Int32 >( bValid, bValid ? AttributeConversion::decodeIntegerHex( aValue ) : 0 );
201 }
202 
getUnsignedHex(sal_Int32 nAttrToken) const203 OptValue< sal_uInt32 > AttributeList::getUnsignedHex( sal_Int32 nAttrToken ) const
204 {
205     OUString aValue = mxAttribs->getOptionalValue( nAttrToken );
206     bool bValid = aValue.getLength() > 0;
207     return OptValue< sal_uInt32 >( bValid, bValid ? AttributeConversion::decodeUnsignedHex( aValue ) : 0 );
208 }
209 
getHyperHex(sal_Int32 nAttrToken) const210 OptValue< sal_Int64 > AttributeList::getHyperHex( sal_Int32 nAttrToken ) const
211 {
212     OUString aValue = mxAttribs->getOptionalValue( nAttrToken );
213     bool bValid = aValue.getLength() > 0;
214     return OptValue< sal_Int64 >( bValid, bValid ? AttributeConversion::decodeHyperHex( aValue ) : 0 );
215 }
216 
getBool(sal_Int32 nAttrToken) const217 OptValue< bool > AttributeList::getBool( sal_Int32 nAttrToken ) const
218 {
219     // boolean attributes may be "t", "f", "true", "false", "on", "off", "1", or "0"
220     switch( getToken( nAttrToken, XML_TOKEN_INVALID ) )
221     {
222         case XML_t:     return OptValue< bool >( true );  // used in VML
223         case XML_true:  return OptValue< bool >( true );
224         case XML_on:    return OptValue< bool >( true );
225         case XML_f:     return OptValue< bool >( false ); // used in VML
226         case XML_false: return OptValue< bool >( false );
227         case XML_off:   return OptValue< bool >( false );
228     }
229     OptValue< sal_Int32 > onValue = getInteger( nAttrToken );
230     return OptValue< bool >( onValue.has(), onValue.get() != 0 );
231 }
232 
getDateTime(sal_Int32 nAttrToken) const233 OptValue< DateTime > AttributeList::getDateTime( sal_Int32 nAttrToken ) const
234 {
235     OUString aValue = mxAttribs->getOptionalValue( nAttrToken );
236     DateTime aDateTime;
237     bool bValid = parseISO8601DateTime( aValue, aDateTime );
238     return OptValue< DateTime >( bValid, aDateTime );
239 }
240 
241 // defaulted return values ----------------------------------------------------
242 
getToken(sal_Int32 nAttrToken,sal_Int32 nDefault) const243 sal_Int32 AttributeList::getToken( sal_Int32 nAttrToken, sal_Int32 nDefault ) const
244 {
245     return mxAttribs->getOptionalValueToken( nAttrToken, nDefault );
246 }
247 
getString(sal_Int32 nAttrToken,const OUString & rDefault) const248 OUString AttributeList::getString( sal_Int32 nAttrToken, const OUString& rDefault ) const
249 {
250     try
251     {
252         return mxAttribs->getValue( nAttrToken );
253     }
254     catch( Exception& )
255     {
256     }
257     return rDefault;
258 }
259 
getXString(sal_Int32 nAttrToken,const OUString & rDefault) const260 OUString AttributeList::getXString( sal_Int32 nAttrToken, const OUString& rDefault ) const
261 {
262     return getXString( nAttrToken ).get( rDefault );
263 }
264 
getDouble(sal_Int32 nAttrToken,double fDefault) const265 double AttributeList::getDouble( sal_Int32 nAttrToken, double fDefault ) const
266 {
267     return getDouble( nAttrToken ).get( fDefault );
268 }
269 
getInteger(sal_Int32 nAttrToken,sal_Int32 nDefault) const270 sal_Int32 AttributeList::getInteger( sal_Int32 nAttrToken, sal_Int32 nDefault ) const
271 {
272     return getInteger( nAttrToken ).get( nDefault );
273 }
274 
getUnsigned(sal_Int32 nAttrToken,sal_uInt32 nDefault) const275 sal_uInt32 AttributeList::getUnsigned( sal_Int32 nAttrToken, sal_uInt32 nDefault ) const
276 {
277     return getUnsigned( nAttrToken ).get( nDefault );
278 }
279 
getHyper(sal_Int32 nAttrToken,sal_Int64 nDefault) const280 sal_Int64 AttributeList::getHyper( sal_Int32 nAttrToken, sal_Int64 nDefault ) const
281 {
282     return getHyper( nAttrToken ).get( nDefault );
283 }
284 
getIntegerHex(sal_Int32 nAttrToken,sal_Int32 nDefault) const285 sal_Int32 AttributeList::getIntegerHex( sal_Int32 nAttrToken, sal_Int32 nDefault ) const
286 {
287     return getIntegerHex( nAttrToken ).get( nDefault );
288 }
289 
getUnsignedHex(sal_Int32 nAttrToken,sal_uInt32 nDefault) const290 sal_uInt32 AttributeList::getUnsignedHex( sal_Int32 nAttrToken, sal_uInt32 nDefault ) const
291 {
292     return getUnsignedHex( nAttrToken ).get( nDefault );
293 }
294 
getHyperHex(sal_Int32 nAttrToken,sal_Int64 nDefault) const295 sal_Int64 AttributeList::getHyperHex( sal_Int32 nAttrToken, sal_Int64 nDefault ) const
296 {
297     return getHyperHex( nAttrToken ).get( nDefault );
298 }
299 
getBool(sal_Int32 nAttrToken,bool bDefault) const300 bool AttributeList::getBool( sal_Int32 nAttrToken, bool bDefault ) const
301 {
302     return getBool( nAttrToken ).get( bDefault );
303 }
304 
getDateTime(sal_Int32 nAttrToken,const DateTime & rDefault) const305 DateTime AttributeList::getDateTime( sal_Int32 nAttrToken, const DateTime& rDefault ) const
306 {
307     return getDateTime( nAttrToken ).get( rDefault );
308 }
309 
310 // ============================================================================
311 
312 } // namespace oox
313