1ca5ec200SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3ca5ec200SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4ca5ec200SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5ca5ec200SAndrew Rist  * distributed with this work for additional information
6ca5ec200SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7ca5ec200SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8ca5ec200SAndrew Rist  * "License"); you may not use this file except in compliance
9ca5ec200SAndrew Rist  * with the License.  You may obtain a copy of the License at
10ca5ec200SAndrew Rist  *
11ca5ec200SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12ca5ec200SAndrew Rist  *
13ca5ec200SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14ca5ec200SAndrew Rist  * software distributed under the License is distributed on an
15ca5ec200SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16ca5ec200SAndrew Rist  * KIND, either express or implied.  See the License for the
17ca5ec200SAndrew Rist  * specific language governing permissions and limitations
18ca5ec200SAndrew Rist  * under the License.
19ca5ec200SAndrew Rist  *
20ca5ec200SAndrew Rist  *************************************************************/
21ca5ec200SAndrew Rist 
22ca5ec200SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir #include "oox/helper/attributelist.hxx"
25*1f71f1d8SDamjan Jovanovic #include "oox/helper/datetimehelper.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include <osl/diagnose.h>
28cdf0e10cSrcweir #include <rtl/ustrbuf.hxx>
29cdf0e10cSrcweir #include "oox/token/tokenmap.hxx"
30cdf0e10cSrcweir 
31cdf0e10cSrcweir namespace oox {
32cdf0e10cSrcweir 
33cdf0e10cSrcweir // ============================================================================
34cdf0e10cSrcweir 
35cdf0e10cSrcweir using namespace ::com::sun::star::uno;
36cdf0e10cSrcweir using namespace ::com::sun::star::util;
37cdf0e10cSrcweir using namespace ::com::sun::star::xml::sax;
38cdf0e10cSrcweir 
39cdf0e10cSrcweir using ::rtl::OUString;
40cdf0e10cSrcweir using ::rtl::OUStringBuffer;
41cdf0e10cSrcweir 
42cdf0e10cSrcweir // ============================================================================
43cdf0e10cSrcweir 
44cdf0e10cSrcweir namespace {
45cdf0e10cSrcweir 
46cdf0e10cSrcweir const sal_Int32 XSTRING_ENCCHAR_LEN     = 7;
47cdf0e10cSrcweir 
lclAddHexDigit(sal_Unicode & orcChar,sal_Unicode cDigit,int nBitShift)48cdf0e10cSrcweir bool lclAddHexDigit( sal_Unicode& orcChar, sal_Unicode cDigit, int nBitShift )
49cdf0e10cSrcweir {
50cdf0e10cSrcweir     if( ('0' <= cDigit) && (cDigit <= '9') ) { orcChar |= ((cDigit - '0') << nBitShift); return true; }
51cdf0e10cSrcweir     if( ('a' <= cDigit) && (cDigit <= 'f') ) { orcChar |= ((cDigit - 'a' + 10) << nBitShift); return true; }
52cdf0e10cSrcweir     if( ('A' <= cDigit) && (cDigit <= 'F') ) { orcChar |= ((cDigit - 'A' + 10) << nBitShift); return true; }
53cdf0e10cSrcweir     return false;
54cdf0e10cSrcweir }
55cdf0e10cSrcweir 
lclGetXChar(const sal_Unicode * & rpcStr,const sal_Unicode * pcEnd)56cdf0e10cSrcweir sal_Unicode lclGetXChar( const sal_Unicode*& rpcStr, const sal_Unicode* pcEnd )
57cdf0e10cSrcweir {
58cdf0e10cSrcweir     sal_Unicode cChar = 0;
59cdf0e10cSrcweir     if( (pcEnd - rpcStr >= XSTRING_ENCCHAR_LEN) &&
60cdf0e10cSrcweir         (rpcStr[ 0 ] == '_') &&
61cdf0e10cSrcweir         (rpcStr[ 1 ] == 'x') &&
62cdf0e10cSrcweir         (rpcStr[ 6 ] == '_') &&
63cdf0e10cSrcweir         lclAddHexDigit( cChar, rpcStr[ 2 ], 12 ) &&
64cdf0e10cSrcweir         lclAddHexDigit( cChar, rpcStr[ 3 ], 8 ) &&
65cdf0e10cSrcweir         lclAddHexDigit( cChar, rpcStr[ 4 ], 4 ) &&
66cdf0e10cSrcweir         lclAddHexDigit( cChar, rpcStr[ 5 ], 0 ) )
67cdf0e10cSrcweir     {
68cdf0e10cSrcweir         rpcStr += XSTRING_ENCCHAR_LEN;
69cdf0e10cSrcweir         return cChar;
70cdf0e10cSrcweir     }
71cdf0e10cSrcweir     return *rpcStr++;
72cdf0e10cSrcweir }
73cdf0e10cSrcweir 
74cdf0e10cSrcweir } // namespace
75cdf0e10cSrcweir 
76cdf0e10cSrcweir // ----------------------------------------------------------------------------
77cdf0e10cSrcweir 
decodeToken(const OUString & rValue)78cdf0e10cSrcweir sal_Int32 AttributeConversion::decodeToken( const OUString& rValue )
79cdf0e10cSrcweir {
80cdf0e10cSrcweir     return StaticTokenMap::get().getTokenFromUnicode( rValue );
81cdf0e10cSrcweir }
82cdf0e10cSrcweir 
decodeXString(const OUString & rValue)83cdf0e10cSrcweir OUString AttributeConversion::decodeXString( const OUString& rValue )
84cdf0e10cSrcweir {
85cdf0e10cSrcweir     // string shorter than one encoded character - no need to decode
86cdf0e10cSrcweir     if( rValue.getLength() < XSTRING_ENCCHAR_LEN )
87cdf0e10cSrcweir         return rValue;
88cdf0e10cSrcweir     OUStringBuffer aBuffer;
89cdf0e10cSrcweir     const sal_Unicode* pcStr = rValue.getStr();
90cdf0e10cSrcweir     const sal_Unicode* pcEnd = pcStr + rValue.getLength();
91cdf0e10cSrcweir     while( pcStr < pcEnd )
92cdf0e10cSrcweir         aBuffer.append( lclGetXChar( pcStr, pcEnd ) );
93cdf0e10cSrcweir     return aBuffer.makeStringAndClear();
94cdf0e10cSrcweir }
95cdf0e10cSrcweir 
decodeDouble(const OUString & rValue)96cdf0e10cSrcweir double AttributeConversion::decodeDouble( const OUString& rValue )
97cdf0e10cSrcweir {
98cdf0e10cSrcweir     return rValue.toDouble();
99cdf0e10cSrcweir }
100cdf0e10cSrcweir 
decodeInteger(const OUString & rValue)101cdf0e10cSrcweir sal_Int32 AttributeConversion::decodeInteger( const OUString& rValue )
102cdf0e10cSrcweir {
103cdf0e10cSrcweir     return rValue.toInt32();
104cdf0e10cSrcweir }
105cdf0e10cSrcweir 
decodeUnsigned(const OUString & rValue)106cdf0e10cSrcweir sal_uInt32 AttributeConversion::decodeUnsigned( const OUString& rValue )
107cdf0e10cSrcweir {
108cdf0e10cSrcweir     return getLimitedValue< sal_uInt32, sal_Int64 >( rValue.toInt64(), 0, SAL_MAX_UINT32 );
109cdf0e10cSrcweir }
110cdf0e10cSrcweir 
decodeHyper(const OUString & rValue)111cdf0e10cSrcweir sal_Int64 AttributeConversion::decodeHyper( const OUString& rValue )
112cdf0e10cSrcweir {
113cdf0e10cSrcweir     return rValue.toInt64();
114cdf0e10cSrcweir }
115cdf0e10cSrcweir 
decodeIntegerHex(const OUString & rValue)116cdf0e10cSrcweir sal_Int32 AttributeConversion::decodeIntegerHex( const OUString& rValue )
117cdf0e10cSrcweir {
118cdf0e10cSrcweir     return rValue.toInt32( 16 );
119cdf0e10cSrcweir }
120cdf0e10cSrcweir 
decodeUnsignedHex(const OUString & rValue)121cdf0e10cSrcweir sal_uInt32 AttributeConversion::decodeUnsignedHex( const OUString& rValue )
122cdf0e10cSrcweir {
123cdf0e10cSrcweir     return getLimitedValue< sal_uInt32, sal_Int64 >( rValue.toInt64( 16 ), 0, SAL_MAX_UINT32 );
124cdf0e10cSrcweir }
125cdf0e10cSrcweir 
decodeHyperHex(const OUString & rValue)126cdf0e10cSrcweir sal_Int64 AttributeConversion::decodeHyperHex( const OUString& rValue )
127cdf0e10cSrcweir {
128cdf0e10cSrcweir     return rValue.toInt64( 16 );
129cdf0e10cSrcweir }
130cdf0e10cSrcweir 
131cdf0e10cSrcweir // ============================================================================
132cdf0e10cSrcweir 
AttributeList(const Reference<XFastAttributeList> & rxAttribs)133cdf0e10cSrcweir AttributeList::AttributeList( const Reference< XFastAttributeList >& rxAttribs ) :
134cdf0e10cSrcweir     mxAttribs( rxAttribs )
135cdf0e10cSrcweir {
136cdf0e10cSrcweir     OSL_ENSURE( mxAttribs.is(), "AttributeList::AttributeList - missing attribute list interface" );
137cdf0e10cSrcweir }
138cdf0e10cSrcweir 
hasAttribute(sal_Int32 nAttrToken) const139cdf0e10cSrcweir bool AttributeList::hasAttribute( sal_Int32 nAttrToken ) const
140cdf0e10cSrcweir {
141cdf0e10cSrcweir     return mxAttribs->hasAttribute( nAttrToken );
142cdf0e10cSrcweir }
143cdf0e10cSrcweir 
144cdf0e10cSrcweir // optional return values -----------------------------------------------------
145cdf0e10cSrcweir 
getToken(sal_Int32 nAttrToken) const146cdf0e10cSrcweir OptValue< sal_Int32 > AttributeList::getToken( sal_Int32 nAttrToken ) const
147cdf0e10cSrcweir {
148cdf0e10cSrcweir     sal_Int32 nToken = mxAttribs->getOptionalValueToken( nAttrToken, XML_TOKEN_INVALID );
149cdf0e10cSrcweir     return OptValue< sal_Int32 >( nToken != XML_TOKEN_INVALID, nToken );
150cdf0e10cSrcweir }
151cdf0e10cSrcweir 
getString(sal_Int32 nAttrToken) const152cdf0e10cSrcweir OptValue< OUString > AttributeList::getString( sal_Int32 nAttrToken ) const
153cdf0e10cSrcweir {
154cdf0e10cSrcweir     // check if the attribute exists (empty string may be different to missing attribute)
155cdf0e10cSrcweir     if( mxAttribs->hasAttribute( nAttrToken ) )
156cdf0e10cSrcweir         return OptValue< OUString >( mxAttribs->getOptionalValue( nAttrToken ) );
157cdf0e10cSrcweir     return OptValue< OUString >();
158cdf0e10cSrcweir }
159cdf0e10cSrcweir 
getXString(sal_Int32 nAttrToken) const160cdf0e10cSrcweir OptValue< OUString > AttributeList::getXString( sal_Int32 nAttrToken ) const
161cdf0e10cSrcweir {
162cdf0e10cSrcweir     // check if the attribute exists (empty string may be different to missing attribute)
163cdf0e10cSrcweir     if( mxAttribs->hasAttribute( nAttrToken ) )
164cdf0e10cSrcweir         return OptValue< OUString >( AttributeConversion::decodeXString( mxAttribs->getOptionalValue( nAttrToken ) ) );
165cdf0e10cSrcweir     return OptValue< OUString >();
166cdf0e10cSrcweir }
167cdf0e10cSrcweir 
getDouble(sal_Int32 nAttrToken) const168cdf0e10cSrcweir OptValue< double > AttributeList::getDouble( sal_Int32 nAttrToken ) const
169cdf0e10cSrcweir {
170cdf0e10cSrcweir     OUString aValue = mxAttribs->getOptionalValue( nAttrToken );
171cdf0e10cSrcweir     bool bValid = aValue.getLength() > 0;
172cdf0e10cSrcweir     return OptValue< double >( bValid, bValid ? AttributeConversion::decodeDouble( aValue ) : 0.0 );
173cdf0e10cSrcweir }
174cdf0e10cSrcweir 
getInteger(sal_Int32 nAttrToken) const175cdf0e10cSrcweir OptValue< sal_Int32 > AttributeList::getInteger( sal_Int32 nAttrToken ) const
176cdf0e10cSrcweir {
177cdf0e10cSrcweir     OUString aValue = mxAttribs->getOptionalValue( nAttrToken );
178cdf0e10cSrcweir     bool bValid = aValue.getLength() > 0;
179cdf0e10cSrcweir     return OptValue< sal_Int32 >( bValid, bValid ? AttributeConversion::decodeInteger( aValue ) : 0 );
180cdf0e10cSrcweir }
181cdf0e10cSrcweir 
getUnsigned(sal_Int32 nAttrToken) const182cdf0e10cSrcweir OptValue< sal_uInt32 > AttributeList::getUnsigned( sal_Int32 nAttrToken ) const
183cdf0e10cSrcweir {
184cdf0e10cSrcweir     OUString aValue = mxAttribs->getOptionalValue( nAttrToken );
185cdf0e10cSrcweir     bool bValid = aValue.getLength() > 0;
186cdf0e10cSrcweir     return OptValue< sal_uInt32 >( bValid, AttributeConversion::decodeUnsigned( aValue ) );
187cdf0e10cSrcweir }
188cdf0e10cSrcweir 
getHyper(sal_Int32 nAttrToken) const189cdf0e10cSrcweir OptValue< sal_Int64 > AttributeList::getHyper( sal_Int32 nAttrToken ) const
190cdf0e10cSrcweir {
191cdf0e10cSrcweir     OUString aValue = mxAttribs->getOptionalValue( nAttrToken );
192cdf0e10cSrcweir     bool bValid = aValue.getLength() > 0;
193cdf0e10cSrcweir     return OptValue< sal_Int64 >( bValid, bValid ? AttributeConversion::decodeHyper( aValue ) : 0 );
194cdf0e10cSrcweir }
195cdf0e10cSrcweir 
getIntegerHex(sal_Int32 nAttrToken) const196cdf0e10cSrcweir OptValue< sal_Int32 > AttributeList::getIntegerHex( sal_Int32 nAttrToken ) const
197cdf0e10cSrcweir {
198cdf0e10cSrcweir     OUString aValue = mxAttribs->getOptionalValue( nAttrToken );
199cdf0e10cSrcweir     bool bValid = aValue.getLength() > 0;
200cdf0e10cSrcweir     return OptValue< sal_Int32 >( bValid, bValid ? AttributeConversion::decodeIntegerHex( aValue ) : 0 );
201cdf0e10cSrcweir }
202cdf0e10cSrcweir 
getUnsignedHex(sal_Int32 nAttrToken) const203cdf0e10cSrcweir OptValue< sal_uInt32 > AttributeList::getUnsignedHex( sal_Int32 nAttrToken ) const
204cdf0e10cSrcweir {
205cdf0e10cSrcweir     OUString aValue = mxAttribs->getOptionalValue( nAttrToken );
206cdf0e10cSrcweir     bool bValid = aValue.getLength() > 0;
207cdf0e10cSrcweir     return OptValue< sal_uInt32 >( bValid, bValid ? AttributeConversion::decodeUnsignedHex( aValue ) : 0 );
208cdf0e10cSrcweir }
209cdf0e10cSrcweir 
getHyperHex(sal_Int32 nAttrToken) const210cdf0e10cSrcweir OptValue< sal_Int64 > AttributeList::getHyperHex( sal_Int32 nAttrToken ) const
211cdf0e10cSrcweir {
212cdf0e10cSrcweir     OUString aValue = mxAttribs->getOptionalValue( nAttrToken );
213cdf0e10cSrcweir     bool bValid = aValue.getLength() > 0;
214cdf0e10cSrcweir     return OptValue< sal_Int64 >( bValid, bValid ? AttributeConversion::decodeHyperHex( aValue ) : 0 );
215cdf0e10cSrcweir }
216cdf0e10cSrcweir 
getBool(sal_Int32 nAttrToken) const217cdf0e10cSrcweir OptValue< bool > AttributeList::getBool( sal_Int32 nAttrToken ) const
218cdf0e10cSrcweir {
219cdf0e10cSrcweir     // boolean attributes may be "t", "f", "true", "false", "on", "off", "1", or "0"
220cdf0e10cSrcweir     switch( getToken( nAttrToken, XML_TOKEN_INVALID ) )
221cdf0e10cSrcweir     {
222cdf0e10cSrcweir         case XML_t:     return OptValue< bool >( true );  // used in VML
223cdf0e10cSrcweir         case XML_true:  return OptValue< bool >( true );
224cdf0e10cSrcweir         case XML_on:    return OptValue< bool >( true );
225cdf0e10cSrcweir         case XML_f:     return OptValue< bool >( false ); // used in VML
226cdf0e10cSrcweir         case XML_false: return OptValue< bool >( false );
227cdf0e10cSrcweir         case XML_off:   return OptValue< bool >( false );
228cdf0e10cSrcweir     }
229cdf0e10cSrcweir     OptValue< sal_Int32 > onValue = getInteger( nAttrToken );
230cdf0e10cSrcweir     return OptValue< bool >( onValue.has(), onValue.get() != 0 );
231cdf0e10cSrcweir }
232cdf0e10cSrcweir 
getDateTime(sal_Int32 nAttrToken) const233cdf0e10cSrcweir OptValue< DateTime > AttributeList::getDateTime( sal_Int32 nAttrToken ) const
234cdf0e10cSrcweir {
235cdf0e10cSrcweir     OUString aValue = mxAttribs->getOptionalValue( nAttrToken );
236cdf0e10cSrcweir     DateTime aDateTime;
237*1f71f1d8SDamjan Jovanovic     bool bValid = parseISO8601DateTime( aValue, aDateTime );
238cdf0e10cSrcweir     return OptValue< DateTime >( bValid, aDateTime );
239cdf0e10cSrcweir }
240cdf0e10cSrcweir 
241cdf0e10cSrcweir // defaulted return values ----------------------------------------------------
242cdf0e10cSrcweir 
getToken(sal_Int32 nAttrToken,sal_Int32 nDefault) const243cdf0e10cSrcweir sal_Int32 AttributeList::getToken( sal_Int32 nAttrToken, sal_Int32 nDefault ) const
244cdf0e10cSrcweir {
245cdf0e10cSrcweir     return mxAttribs->getOptionalValueToken( nAttrToken, nDefault );
246cdf0e10cSrcweir }
247cdf0e10cSrcweir 
getString(sal_Int32 nAttrToken,const OUString & rDefault) const248cdf0e10cSrcweir OUString AttributeList::getString( sal_Int32 nAttrToken, const OUString& rDefault ) const
249cdf0e10cSrcweir {
250cdf0e10cSrcweir     try
251cdf0e10cSrcweir     {
252cdf0e10cSrcweir         return mxAttribs->getValue( nAttrToken );
253cdf0e10cSrcweir     }
254cdf0e10cSrcweir     catch( Exception& )
255cdf0e10cSrcweir     {
256cdf0e10cSrcweir     }
257cdf0e10cSrcweir     return rDefault;
258cdf0e10cSrcweir }
259cdf0e10cSrcweir 
getXString(sal_Int32 nAttrToken,const OUString & rDefault) const260cdf0e10cSrcweir OUString AttributeList::getXString( sal_Int32 nAttrToken, const OUString& rDefault ) const
261cdf0e10cSrcweir {
262cdf0e10cSrcweir     return getXString( nAttrToken ).get( rDefault );
263cdf0e10cSrcweir }
264cdf0e10cSrcweir 
getDouble(sal_Int32 nAttrToken,double fDefault) const265cdf0e10cSrcweir double AttributeList::getDouble( sal_Int32 nAttrToken, double fDefault ) const
266cdf0e10cSrcweir {
267cdf0e10cSrcweir     return getDouble( nAttrToken ).get( fDefault );
268cdf0e10cSrcweir }
269cdf0e10cSrcweir 
getInteger(sal_Int32 nAttrToken,sal_Int32 nDefault) const270cdf0e10cSrcweir sal_Int32 AttributeList::getInteger( sal_Int32 nAttrToken, sal_Int32 nDefault ) const
271cdf0e10cSrcweir {
272cdf0e10cSrcweir     return getInteger( nAttrToken ).get( nDefault );
273cdf0e10cSrcweir }
274cdf0e10cSrcweir 
getUnsigned(sal_Int32 nAttrToken,sal_uInt32 nDefault) const275cdf0e10cSrcweir sal_uInt32 AttributeList::getUnsigned( sal_Int32 nAttrToken, sal_uInt32 nDefault ) const
276cdf0e10cSrcweir {
277cdf0e10cSrcweir     return getUnsigned( nAttrToken ).get( nDefault );
278cdf0e10cSrcweir }
279cdf0e10cSrcweir 
getHyper(sal_Int32 nAttrToken,sal_Int64 nDefault) const280cdf0e10cSrcweir sal_Int64 AttributeList::getHyper( sal_Int32 nAttrToken, sal_Int64 nDefault ) const
281cdf0e10cSrcweir {
282cdf0e10cSrcweir     return getHyper( nAttrToken ).get( nDefault );
283cdf0e10cSrcweir }
284cdf0e10cSrcweir 
getIntegerHex(sal_Int32 nAttrToken,sal_Int32 nDefault) const285cdf0e10cSrcweir sal_Int32 AttributeList::getIntegerHex( sal_Int32 nAttrToken, sal_Int32 nDefault ) const
286cdf0e10cSrcweir {
287cdf0e10cSrcweir     return getIntegerHex( nAttrToken ).get( nDefault );
288cdf0e10cSrcweir }
289cdf0e10cSrcweir 
getUnsignedHex(sal_Int32 nAttrToken,sal_uInt32 nDefault) const290cdf0e10cSrcweir sal_uInt32 AttributeList::getUnsignedHex( sal_Int32 nAttrToken, sal_uInt32 nDefault ) const
291cdf0e10cSrcweir {
292cdf0e10cSrcweir     return getUnsignedHex( nAttrToken ).get( nDefault );
293cdf0e10cSrcweir }
294cdf0e10cSrcweir 
getHyperHex(sal_Int32 nAttrToken,sal_Int64 nDefault) const295cdf0e10cSrcweir sal_Int64 AttributeList::getHyperHex( sal_Int32 nAttrToken, sal_Int64 nDefault ) const
296cdf0e10cSrcweir {
297cdf0e10cSrcweir     return getHyperHex( nAttrToken ).get( nDefault );
298cdf0e10cSrcweir }
299cdf0e10cSrcweir 
getBool(sal_Int32 nAttrToken,bool bDefault) const300cdf0e10cSrcweir bool AttributeList::getBool( sal_Int32 nAttrToken, bool bDefault ) const
301cdf0e10cSrcweir {
302cdf0e10cSrcweir     return getBool( nAttrToken ).get( bDefault );
303cdf0e10cSrcweir }
304cdf0e10cSrcweir 
getDateTime(sal_Int32 nAttrToken,const DateTime & rDefault) const305cdf0e10cSrcweir DateTime AttributeList::getDateTime( sal_Int32 nAttrToken, const DateTime& rDefault ) const
306cdf0e10cSrcweir {
307cdf0e10cSrcweir     return getDateTime( nAttrToken ).get( rDefault );
308cdf0e10cSrcweir }
309cdf0e10cSrcweir 
310cdf0e10cSrcweir // ============================================================================
311cdf0e10cSrcweir 
312cdf0e10cSrcweir } // namespace oox
313