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