1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: sequence.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_configmgr.hxx"
34 #include "datalock.hxx"
35 #include "sequence.hxx"
38 #ifndef INCLUDED_ALGORITHM
40 #define INCLUDED_ALGORITHM
43 #ifndef INCLUDED_STRING_H
45 #define INCLUDED_STRING_H
48 #include "utility.hxx"
50 #ifndef SIMPLE_REFERENCE_FAST
56 //-----------------------------------------------------------------------------
59 //-----------------------------------------------------------------------------
60 namespace Type
= data::Type
;
61 namespace uno
= ::com::sun::star::uno
;
62 //-----------------------------------------------------------------------------
64 sal_uInt32
implGetElementSize(sal_uInt8 _aElementType
)
66 OSL_ASSERT(_aElementType
== (_aElementType
& Type::mask_basetype
));
67 switch (_aElementType
)
70 case Type::value_boolean
: return sizeof(sal_Bool
);
72 case Type::value_short
: return sizeof(sal_Int16
);
74 case Type::value_int
: return sizeof(sal_Int32
);
76 case Type::value_long
: return sizeof(sal_Int64
);
78 case Type::value_double
: return sizeof(double);
80 case Type::value_string
: return sizeof(rtl_uString
*);
82 case Type::value_binary
: return sizeof(sal_uInt8
*);
84 case Type::value_any
: // results from value_invalid
86 OSL_ENSURE( false, "Invalid type code" );
91 //-----------------------------------------------------------------------------
93 sal_uInt32
implGetHeaderSize(sal_uInt32 _nElemSize
)
95 // pad header to elem size, if larger (for safe alignment)
96 OSL_ASSERT(_nElemSize
> sizeof(sal_Int32
) || sizeof(sal_Int32
) % _nElemSize
== 0);
97 return _nElemSize
> sizeof(sal_Int32
) ? _nElemSize
: sizeof(sal_Int32
);
100 //-----------------------------------------------------------------------------
103 sal_Int32
& implGetSize(sal_uInt8
* _aSeq
)
105 return * (sal_Int32
*) _aSeq
;
108 //-----------------------------------------------------------------------------
110 sal_uInt8
* implSeqAlloc(sal_Int32 _nElements
, sal_uInt32 _nElemSize
)
112 sal_uInt32 nTotalSize
= implGetHeaderSize(_nElemSize
) + _nElements
* _nElemSize
;
114 sal_uInt8
* aResult
= (sal_uInt8
*) (new sal_uInt8
[nTotalSize
]);
116 implGetSize(aResult
) = _nElements
;
121 //-----------------------------------------------------------------------------
124 void allocSeqData(sal_uInt8
*_pDestAddr
,
125 sal_uInt8 _aElementType
,
126 sal_Int32 _nElements
, sal_uInt32 _nElementSize
,
127 void const * _pSourceData
)
129 OSL_ASSERT(_aElementType
== (_aElementType
& Type::mask_basetype
));
130 OSL_ASSERT(_nElementSize
== implGetElementSize(_aElementType
));
131 switch (_aElementType
)
133 case Type::value_boolean
:
134 case Type::value_short
:
135 case Type::value_int
:
136 case Type::value_long
:
137 case Type::value_double
:
138 ::memcpy(_pDestAddr
,_pSourceData
,_nElements
* _nElementSize
);
141 case Type::value_string
:
143 OSL_ASSERT(_nElementSize
== sizeof(rtl_uString
*));
145 rtl::OUString
const * pSource
= static_cast<rtl::OUString
const *>(_pSourceData
);
147 while (--_nElements
>= 0)
149 rtl_uString
* aElement
= acquireString(*pSource
);
151 rtl_uString
* * pDest
= reinterpret_cast<rtl_uString
**>(_pDestAddr
);
155 _pDestAddr
+= sizeof *pDest
;
160 case Type::value_binary
:
162 OSL_ASSERT(_nElementSize
== sizeof(sal_uInt8
*));
164 uno::Sequence
< sal_Int8
> const * pSource
= static_cast<uno::Sequence
< sal_Int8
> const *>(_pSourceData
);
166 while (--_nElements
>= 0)
168 sal_uInt8
* aElement
= allocBinary(*pSource
);
170 sal_uInt8
* * pDest
= (sal_uInt8
* *) _pDestAddr
;
174 _pDestAddr
+= sizeof *pDest
;
179 case Type::value_any
:
181 OSL_ENSURE(false, "Invalid element type");
186 //-----------------------------------------------------------------------------
187 sal_uInt8
* allocSequence(sal_uInt8 _aElementType
, ::sal_Sequence
const * _pSeqData
)
189 OSL_ENSURE(_aElementType
== (_aElementType
& Type::mask_valuetype
), "Invalid type code");
191 OSL_ENSURE(_pSeqData
, "ERROR: Trying to allocate from a NULL sequence");
192 if (_pSeqData
== NULL
) return 0;
194 // OSL_ASSERT(_aElementType == (_aElementType & Type::mask_basetype));
195 _aElementType
&= Type::mask_basetype
;
197 sal_uInt32
const nElementSize
= implGetElementSize(_aElementType
);
198 sal_Int32
const nElements
= _pSeqData
->nElements
;
200 sal_uInt8
* aResult
= implSeqAlloc(nElements
,nElementSize
);
203 allocSeqData( aResult
+ implGetHeaderSize(nElementSize
),
204 _aElementType
, nElements
, nElementSize
,
205 _pSeqData
->elements
);
210 //-----------------------------------------------------------------------------
211 sal_uInt8
* allocBinary(uno::Sequence
<sal_Int8
> const & _aBinaryValue
)
213 sal_uInt32
const nElementSize
= 1;
214 sal_Int32
const nLength
= _aBinaryValue
.getLength();
216 sal_uInt8
* aResult
= implSeqAlloc(nLength
,nElementSize
);
220 sal_uInt8
*pElementBaseAddr
= aResult
+ implGetHeaderSize(nElementSize
);
221 ::memcpy(pElementBaseAddr
, _aBinaryValue
.getConstArray(), nLength
);
227 //-----------------------------------------------------------------------------
229 void freeSeqData(sal_uInt8
*_pDataAddr
,
230 sal_uInt8 _aElementType
, sal_Int32 _nElements
)
232 OSL_ASSERT(_aElementType
== (_aElementType
& Type::mask_basetype
));
234 switch (_aElementType
)
236 case Type::value_boolean
:
237 case Type::value_short
:
238 case Type::value_int
:
239 case Type::value_long
:
240 case Type::value_double
:
244 case Type::value_string
:
246 rtl_uString
* * pElements
= reinterpret_cast<rtl_uString
**>( _pDataAddr
);
248 for (sal_Int32 i
= 0; i
< _nElements
; ++i
)
250 rtl_uString_release(pElements
[i
]);
255 case Type::value_binary
:
257 sal_uInt8
* * pElements
= reinterpret_cast<sal_uInt8
**>( _pDataAddr
);
259 for (sal_Int32 i
= 0; i
< _nElements
; ++i
)
261 freeBinary(pElements
[i
]);
266 case Type::value_any
:
268 OSL_ENSURE(false, "Invalid element type");
273 //-----------------------------------------------------------------------------
274 void freeSequence(sal_uInt8 _aElementType
, sal_uInt8
* _aSeq
)
276 OSL_ENSURE(_aElementType
== (_aElementType
& Type::mask_valuetype
), "Invalid type code");
278 OSL_ENSURE(_aSeq
, "ERROR: Trying to free a NULL sequence");
279 if (_aSeq
== 0) return;
281 // OSL_ASSERT(_aElementType == (_aElementType & Type::mask_basetype));
282 _aElementType
&= Type::mask_basetype
;
284 sal_uInt32 nHeaderSize
= implGetHeaderSize( implGetElementSize( _aElementType
) );
286 freeSeqData(_aSeq
+ nHeaderSize
, _aElementType
, implGetSize(_aSeq
));
288 delete[] (sal_uInt8
*)_aSeq
;
291 //-----------------------------------------------------------------------------
292 void freeBinary(sal_uInt8
* _aSeq
)
294 OSL_ENSURE(_aSeq
, "ERROR: Trying to free a NULL sequence");
295 if (_aSeq
== 0) return;
297 delete[] (sal_uInt8
*)_aSeq
;
300 //-----------------------------------------------------------------------------
303 sal_Sequence
* implCreateSequence(void const * _pElements
, sal_uInt8 _aElementType
, sal_Int32 _nElements
)
305 uno::Type aUnoType
= getUnoType( sal_uInt8( _aElementType
| Type::flag_sequence
));
307 sal_Sequence
* pResult
= NULL
;
308 ::uno_type_sequence_construct( &pResult
, aUnoType
.getTypeLibType(),
309 const_cast< void * >( _pElements
),
312 OSL_ASSERT(pResult
->nRefCount
== 1);
316 //-----------------------------------------------------------------------------
318 sal_Sequence
* readSeqData(sal_uInt8
*_pDataAddr
, sal_uInt8 _aElementType
, sal_Int32 _nElements
)
320 OSL_ASSERT(_aElementType
== (_aElementType
& Type::mask_basetype
));
322 void const * pElementData
= (void const *)_pDataAddr
;
323 switch (_aElementType
)
325 case Type::value_boolean
:
326 case Type::value_short
:
327 case Type::value_int
:
328 case Type::value_long
:
329 case Type::value_double
:
330 return implCreateSequence(pElementData
,_aElementType
,_nElements
);
332 case Type::value_string
:
334 uno::Sequence
<rtl::OUString
> aResult(_nElements
);
335 rtl::OUString
* pResult
= aResult
.getArray();
337 rtl_uString
* const * pElements
= static_cast<rtl_uString
* const *>( pElementData
);
339 for (sal_Int32 i
= 0; i
< _nElements
; ++i
)
341 pResult
[i
] = rtl::OUString(pElements
[i
]);
344 sal_Sequence
* pRet
= aResult
.get();
349 case Type::value_binary
:
351 uno::Sequence
< uno::Sequence
< sal_Int8
> > aResult(_nElements
);
352 uno::Sequence
< sal_Int8
> * pResult
= aResult
.getArray();
354 sal_uInt8
* const * pElements
= static_cast<sal_uInt8
* const *>( pElementData
);
356 for (sal_Int32 i
= 0; i
< _nElements
; ++i
)
358 pResult
[i
] = readBinary(pElements
[i
]);
361 sal_Sequence
* pRet
= aResult
.get();
366 case Type::value_any
:
368 OSL_ENSURE(false, "Invalid element type");
373 //-----------------------------------------------------------------------------
375 ::sal_Sequence
* readSequence(sal_uInt8 _aElementType
, sal_uInt8
* _aSeq
)
377 OSL_ENSURE(_aElementType
== (_aElementType
& Type::mask_valuetype
), "Invalid type code");
379 OSL_ENSURE(_aSeq
, "ERROR: Trying to read from a NULL sequence");
380 if (_aSeq
== 0) return NULL
;
382 // OSL_ASSERT(_aElementType == (_aElementType & Type::mask_basetype));
383 _aElementType
&= Type::mask_basetype
;
385 sal_uInt32 nHeaderSize
= implGetHeaderSize( implGetElementSize( _aElementType
) );
387 return readSeqData(_aSeq
+ nHeaderSize
, _aElementType
, implGetSize(_aSeq
));
390 //-----------------------------------------------------------------------------
391 uno::Any
readAnySequence(sal_uInt8 _aElementType
, sal_uInt8
* _aSeq
)
393 sal_Sequence
* pRawSequence
= readSequence(_aElementType
, _aSeq
);
397 if (pRawSequence
!= NULL
)
398 switch (_aElementType
& Type::mask_basetype
)
400 case Type::value_string
:
402 uno::Sequence
< rtl::OUString
> aSequence(pRawSequence
,SAL_NO_ACQUIRE
);
403 aResult
<<=aSequence
;
407 case Type::value_boolean
:
409 uno::Sequence
< sal_Bool
> aSequence(pRawSequence
,SAL_NO_ACQUIRE
);
410 aResult
<<=aSequence
;
414 case Type::value_short
:
416 uno::Sequence
< sal_Int16
> aSequence(pRawSequence
,SAL_NO_ACQUIRE
);
417 aResult
<<=aSequence
;
421 case Type::value_int
:
423 uno::Sequence
< sal_Int32
> aSequence(pRawSequence
,SAL_NO_ACQUIRE
);
424 aResult
<<=aSequence
;
428 case Type::value_long
:
430 uno::Sequence
< sal_Int64
> aSequence(pRawSequence
,SAL_NO_ACQUIRE
);
431 aResult
<<=aSequence
;
435 case Type::value_double
:
437 uno::Sequence
< double > aSequence(pRawSequence
,SAL_NO_ACQUIRE
);
438 aResult
<<=aSequence
;
442 case Type::value_binary
:
444 uno::Sequence
< uno::Sequence
< sal_Int8
> > aSequence(pRawSequence
,SAL_NO_ACQUIRE
);
445 aResult
<<=aSequence
;
449 case Type::value_any
: // from value_invalid ??
451 OSL_ENSURE( false, "Invalid type code" );
455 OSL_ASSERT(!aResult
.hasValue() || aResult
.getValueType() == getUnoType(sal_uInt8(_aElementType
| Type::flag_sequence
)));
460 //-----------------------------------------------------------------------------
461 uno::Sequence
<sal_Int8
> readBinary(sal_uInt8
* _aSeq
)
463 OSL_ENSURE(_aSeq
, "ERROR: Trying to read from a NULL sequence");
464 if (_aSeq
== 0) return uno::Sequence
<sal_Int8
>();
466 return uno::Sequence
< sal_Int8
>((const sal_Int8
*)(_aSeq
+ implGetHeaderSize(1)),
470 //-----------------------------------------------------------------------------
472 //-----------------------------------------------------------------------------
475 // Remaining 'global' mutex bits - should move to api2 ...
478 osl::Mutex
UnoApiLock::aCoreLock
;
479 volatile oslInterlockedCount
UnoApiLock::nHeld
= 0;
481 UnoApiLockReleaser::UnoApiLockReleaser()
483 mnCount
= UnoApiLock::nHeld
;
484 for (oslInterlockedCount i
= 0; i
< mnCount
; i
++)
485 UnoApiLock::release();
488 UnoApiLockReleaser::~UnoApiLockReleaser()
490 for (oslInterlockedCount i
= 0; i
< mnCount
; i
++)
491 UnoApiLock::acquire();
493 } // namespace configmgr