merge the formfield patch from ooo-build
[ooovba.git] / configmgr / source / data / sequence.cxx
blobdfcd4c39b8f635f1b5e1e68d55e50f94fadeeb7a
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: sequence.cxx,v $
10 * $Revision: 1.9 $
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"
36 #include "flags.hxx"
38 #ifndef INCLUDED_ALGORITHM
39 #include <algorithm>
40 #define INCLUDED_ALGORITHM
41 #endif
43 #ifndef INCLUDED_STRING_H
44 #include <string.h>
45 #define INCLUDED_STRING_H
46 #endif
48 #include "utility.hxx"
50 #ifndef SIMPLE_REFERENCE_FAST
51 # include <stdio.h>
52 #endif
54 namespace configmgr
56 //-----------------------------------------------------------------------------
57 namespace sharable
59 //-----------------------------------------------------------------------------
60 namespace Type = data::Type;
61 namespace uno = ::com::sun::star::uno;
62 //-----------------------------------------------------------------------------
63 static
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
85 default:
86 OSL_ENSURE( false, "Invalid type code" );
87 return 0;
91 //-----------------------------------------------------------------------------
92 static inline
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 //-----------------------------------------------------------------------------
101 static
102 inline
103 sal_Int32& implGetSize(sal_uInt8 * _aSeq)
105 return * (sal_Int32 *) _aSeq;
108 //-----------------------------------------------------------------------------
109 static
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;
118 return aResult;
121 //-----------------------------------------------------------------------------
123 static
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);
139 break;
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);
152 *pDest = aElement;
154 ++pSource;
155 _pDestAddr += sizeof *pDest;
158 break;
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;
171 *pDest = aElement;
173 ++pSource;
174 _pDestAddr += sizeof *pDest;
177 break;
179 case Type::value_any:
180 default:
181 OSL_ENSURE(false, "Invalid element type");
182 break;
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);
202 if (aResult)
203 allocSeqData( aResult + implGetHeaderSize(nElementSize),
204 _aElementType, nElements, nElementSize,
205 _pSeqData->elements);
207 return aResult;
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);
218 if (aResult)
220 sal_uInt8 *pElementBaseAddr = aResult + implGetHeaderSize(nElementSize);
221 ::memcpy(pElementBaseAddr, _aBinaryValue.getConstArray(), nLength);
224 return aResult;
227 //-----------------------------------------------------------------------------
228 static
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:
241 // nothing to do
242 break;
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]);
253 break;
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]);
264 break;
266 case Type::value_any:
267 default:
268 OSL_ENSURE(false, "Invalid element type");
269 break;
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 //-----------------------------------------------------------------------------
302 static inline
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 ),
310 _nElements, NULL );
312 OSL_ASSERT(pResult->nRefCount == 1);
313 return pResult;
316 //-----------------------------------------------------------------------------
317 static
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();
345 ++pRet->nRefCount;
346 return pRet;
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();
362 ++pRet->nRefCount;
363 return pRet;
366 case Type::value_any:
367 default:
368 OSL_ENSURE(false, "Invalid element type");
369 return NULL;
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);
395 uno::Any aResult;
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 ;
405 break;
407 case Type::value_boolean:
409 uno::Sequence< sal_Bool > aSequence(pRawSequence,SAL_NO_ACQUIRE);
410 aResult <<=aSequence ;
412 break;
414 case Type::value_short:
416 uno::Sequence< sal_Int16 > aSequence(pRawSequence,SAL_NO_ACQUIRE);
417 aResult <<=aSequence ;
419 break;
421 case Type::value_int:
423 uno::Sequence< sal_Int32 > aSequence(pRawSequence,SAL_NO_ACQUIRE);
424 aResult <<=aSequence ;
426 break;
428 case Type::value_long:
430 uno::Sequence< sal_Int64 > aSequence(pRawSequence,SAL_NO_ACQUIRE);
431 aResult <<=aSequence ;
433 break;
435 case Type::value_double:
437 uno::Sequence< double > aSequence(pRawSequence,SAL_NO_ACQUIRE);
438 aResult <<=aSequence ;
440 break;
442 case Type::value_binary:
444 uno::Sequence< uno::Sequence< sal_Int8 > > aSequence(pRawSequence,SAL_NO_ACQUIRE);
445 aResult <<=aSequence ;
447 break;
449 case Type::value_any: // from value_invalid ??
450 default:
451 OSL_ENSURE( false, "Invalid type code" );
452 break;
455 OSL_ASSERT(!aResult.hasValue() || aResult.getValueType() == getUnoType(sal_uInt8(_aElementType | Type::flag_sequence)));
457 return aResult;
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)),
467 implGetSize(_aSeq));
470 //-----------------------------------------------------------------------------
472 //-----------------------------------------------------------------------------
473 } // namespace
475 // Remaining 'global' mutex bits - should move to api2 ...
476 namespace configmgr
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