xref: /trunk/main/cppu/source/uno/sequence.cxx (revision 129fa3d1)
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 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_cppu.hxx"
26 #include <rtl/memory.h>
27 #include <rtl/alloc.h>
28 #include <osl/diagnose.h>
29 #include <osl/interlck.h>
30 #include <typelib/typedescription.h>
31 #include <uno/data.h>
32 #include <uno/dispatcher.h>
33 #include <uno/sequence2.h>
34 
35 #include "constr.hxx"
36 #include "copy.hxx"
37 #include "destr.hxx"
38 
39 
40 using namespace cppu;
41 
42 namespace cppu
43 {
44 
45 //------------------------------------------------------------------------------
reallocSeq(uno_Sequence * pReallocate,sal_Size nElementSize,sal_Int32 nElements)46 static inline uno_Sequence * reallocSeq(
47 	uno_Sequence * pReallocate, sal_Size nElementSize, sal_Int32 nElements )
48 {
49     OSL_ASSERT( nElements >= 0 );
50     uno_Sequence * pNew = 0;
51     sal_uInt32 nSize = calcSeqMemSize( nElementSize, nElements );
52     if (nSize > 0)
53     {
54         if (pReallocate == 0)
55         {
56             pNew = (uno_Sequence *) rtl_allocateMemory( nSize );
57         }
58         else
59         {
60             pNew = (uno_Sequence *) rtl_reallocateMemory( pReallocate, nSize );
61         }
62         if (pNew != 0)
63         {
64             // header init
65             pNew->nRefCount = 1;
66             pNew->nElements = nElements;
67         }
68     }
69     return pNew;
70 }
71 
72 //------------------------------------------------------------------------------
idefaultConstructElements(uno_Sequence ** ppSeq,typelib_TypeDescriptionReference * pElementType,sal_Int32 nStartIndex,sal_Int32 nStopIndex,sal_Int32 nAlloc=-1)73 static inline bool idefaultConstructElements(
74 	uno_Sequence ** ppSeq,
75 	typelib_TypeDescriptionReference * pElementType,
76 	sal_Int32 nStartIndex, sal_Int32 nStopIndex,
77 	sal_Int32 nAlloc = -1 ) // >= 0 means (re)alloc memory for nAlloc elements
78 {
79     uno_Sequence * pSeq = *ppSeq;
80 	switch (pElementType->eTypeClass)
81 	{
82 	case typelib_TypeClass_CHAR:
83 		if (nAlloc >= 0)
84             pSeq = reallocSeq( pSeq, sizeof(sal_Unicode), nAlloc );
85         if (pSeq != 0)
86         {
87             ::rtl_zeroMemory(
88                 pSeq->elements + (sizeof(sal_Unicode) * nStartIndex),
89                 sizeof(sal_Unicode) * (nStopIndex - nStartIndex) );
90         }
91 		break;
92 	case typelib_TypeClass_BOOLEAN:
93 		if (nAlloc >= 0)
94             pSeq = reallocSeq( pSeq, sizeof(sal_Bool), nAlloc );
95         if (pSeq != 0)
96         {
97             ::rtl_zeroMemory(
98                 pSeq->elements + (sizeof(sal_Bool) * nStartIndex),
99                 sizeof(sal_Bool) * (nStopIndex - nStartIndex) );
100         }
101 		break;
102 	case typelib_TypeClass_BYTE:
103 		if (nAlloc >= 0)
104             pSeq = reallocSeq( pSeq, sizeof(sal_Int8), nAlloc );
105         if (pSeq != 0)
106         {
107             ::rtl_zeroMemory(
108                 pSeq->elements + (sizeof(sal_Int8) * nStartIndex),
109                 sizeof(sal_Int8) * (nStopIndex - nStartIndex) );
110         }
111 		break;
112 	case typelib_TypeClass_SHORT:
113 	case typelib_TypeClass_UNSIGNED_SHORT:
114 		if (nAlloc >= 0)
115             pSeq = reallocSeq( pSeq, sizeof(sal_Int16), nAlloc );
116         if (pSeq != 0)
117         {
118             ::rtl_zeroMemory(
119                 pSeq->elements + (sizeof(sal_Int16) * nStartIndex),
120                 sizeof(sal_Int16) * (nStopIndex - nStartIndex) );
121         }
122 		break;
123 	case typelib_TypeClass_LONG:
124 	case typelib_TypeClass_UNSIGNED_LONG:
125 		if (nAlloc >= 0)
126             pSeq = reallocSeq( pSeq, sizeof(sal_Int32), nAlloc );
127         if (pSeq != 0)
128         {
129             ::rtl_zeroMemory(
130                 pSeq->elements + (sizeof(sal_Int32) * nStartIndex),
131                 sizeof(sal_Int32) * (nStopIndex - nStartIndex) );
132         }
133 		break;
134 	case typelib_TypeClass_HYPER:
135 	case typelib_TypeClass_UNSIGNED_HYPER:
136 		if (nAlloc >= 0)
137             pSeq = reallocSeq( pSeq, sizeof(sal_Int64), nAlloc );
138         if (pSeq != 0)
139         {
140             ::rtl_zeroMemory(
141                 pSeq->elements + (sizeof(sal_Int64) * nStartIndex),
142                 sizeof(sal_Int64) * (nStopIndex - nStartIndex) );
143         }
144 		break;
145 	case typelib_TypeClass_FLOAT:
146 	{
147 		if (nAlloc >= 0)
148             pSeq = reallocSeq( pSeq, sizeof(float), nAlloc );
149         if (pSeq != 0)
150         {
151             float * pElements = (float *) pSeq->elements;
152             for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos )
153             {
154                 pElements[nPos] = 0.0;
155             }
156         }
157 		break;
158 	}
159 	case typelib_TypeClass_DOUBLE:
160 	{
161 		if (nAlloc >= 0)
162             pSeq = reallocSeq( pSeq, sizeof(double), nAlloc );
163         if (pSeq != 0)
164         {
165             double * pElements = (double *) pSeq->elements;
166             for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos )
167             {
168                 pElements[nPos] = 0.0;
169             }
170         }
171 		break;
172 	}
173 	case typelib_TypeClass_STRING:
174 	{
175 		if (nAlloc >= 0)
176             pSeq = reallocSeq( pSeq, sizeof(rtl_uString *), nAlloc );
177         if (pSeq != 0)
178         {
179             rtl_uString ** pElements = (rtl_uString **) pSeq->elements;
180             for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos )
181             {
182                 pElements[nPos] = 0;
183                 rtl_uString_new( &pElements[nPos] );
184             }
185         }
186 		break;
187 	}
188 	case typelib_TypeClass_TYPE:
189 	{
190 		if (nAlloc >= 0)
191         {
192             pSeq = reallocSeq(
193                 pSeq, sizeof(typelib_TypeDescriptionReference *), nAlloc );
194         }
195         if (pSeq != 0)
196         {
197             typelib_TypeDescriptionReference ** pElements =
198                 (typelib_TypeDescriptionReference **) pSeq->elements;
199             for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos )
200             {
201                 pElements[nPos] = _getVoidType();
202             }
203         }
204 		break;
205 	}
206 	case typelib_TypeClass_ANY:
207 	{
208 		if (nAlloc >= 0)
209             pSeq = reallocSeq( pSeq, sizeof(uno_Any), nAlloc );
210         if (pSeq != 0)
211         {
212             uno_Any * pElements = (uno_Any *) pSeq->elements;
213             for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos )
214             {
215                 CONSTRUCT_EMPTY_ANY( &pElements[nPos] );
216             }
217         }
218 		break;
219 	}
220 	case typelib_TypeClass_ENUM:
221 	{
222 		if (nAlloc >= 0)
223             pSeq = reallocSeq( pSeq, sizeof(sal_Int32), nAlloc );
224         if (pSeq != 0)
225         {
226             typelib_TypeDescription * pElementTypeDescr = 0;
227             TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType );
228             sal_Int32 eEnum =
229                 ((typelib_EnumTypeDescription *)
230                  pElementTypeDescr)->nDefaultEnumValue;
231             TYPELIB_DANGER_RELEASE( pElementTypeDescr );
232 
233             sal_Int32 * pElements = (sal_Int32 *) pSeq->elements;
234             for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos )
235             {
236                 pElements[nPos] = eEnum;
237             }
238         }
239 		break;
240 	}
241 	case typelib_TypeClass_STRUCT:
242 	case typelib_TypeClass_EXCEPTION:
243 	{
244 		typelib_TypeDescription * pElementTypeDescr = 0;
245 		TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType );
246 		sal_Int32 nElementSize = pElementTypeDescr->nSize;
247 
248 		if (nAlloc >= 0)
249             pSeq = reallocSeq( pSeq, nElementSize, nAlloc );
250         if (pSeq != 0)
251         {
252             char * pElements = pSeq->elements;
253             for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos )
254             {
255                 _defaultConstructStruct(
256                     pElements + (nElementSize * nPos),
257                     (typelib_CompoundTypeDescription *)pElementTypeDescr );
258             }
259         }
260 
261 		TYPELIB_DANGER_RELEASE( pElementTypeDescr );
262 		break;
263 	}
264 	case typelib_TypeClass_ARRAY:
265 	{
266 		typelib_TypeDescription * pElementTypeDescr = 0;
267 		TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType );
268 		sal_Int32 nElementSize = pElementTypeDescr->nSize;
269 
270 		if (nAlloc >= 0)
271             pSeq = reallocSeq( pSeq, nElementSize, nAlloc );
272         if (pSeq != 0)
273         {
274             char * pElements = pSeq->elements;
275             for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos )
276             {
277                 _defaultConstructArray(
278                     pElements + (nElementSize * nPos),
279                     (typelib_ArrayTypeDescription *)pElementTypeDescr );
280             }
281         }
282 
283 		TYPELIB_DANGER_RELEASE( pElementTypeDescr );
284 		break;
285 	}
286 	case typelib_TypeClass_UNION:
287 	{
288 		typelib_TypeDescription * pElementTypeDescr = 0;
289 		TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType );
290 		sal_Int32 nElementSize = pElementTypeDescr->nSize;
291 
292 		if (nAlloc >= 0)
293             pSeq = reallocSeq( pSeq, nElementSize, nAlloc );
294         if (pSeq != 0)
295         {
296             sal_Int32 nValueOffset =
297                 ((typelib_UnionTypeDescription *)
298                  pElementTypeDescr)->nValueOffset;
299             sal_Int64 nDefaultDiscr =
300                 ((typelib_UnionTypeDescription *)
301                  pElementTypeDescr)->nDefaultDiscriminant;
302 
303             typelib_TypeDescription * pDefaultTypeDescr = 0;
304             TYPELIB_DANGER_GET(
305                 &pDefaultTypeDescr,
306                 ((typelib_UnionTypeDescription *)
307                  pElementTypeDescr)->pDefaultTypeRef );
308 
309             char * pElements = pSeq->elements;
310             for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos )
311             {
312                 char * pMem = pElements + (nElementSize * nPos);
313                 ::uno_constructData(
314                     (char *)pMem + nValueOffset, pDefaultTypeDescr );
315                 *(sal_Int64 *)pMem = nDefaultDiscr;
316             }
317             TYPELIB_DANGER_RELEASE( pDefaultTypeDescr );
318         }
319 
320         TYPELIB_DANGER_RELEASE( pElementTypeDescr );
321 		break;
322 	}
323 	case typelib_TypeClass_SEQUENCE:
324 	{
325 		if (nAlloc >= 0)
326             pSeq = reallocSeq( pSeq, sizeof(uno_Sequence *), nAlloc );
327         if (pSeq != 0)
328         {
329             uno_Sequence ** pElements =
330                 (uno_Sequence **) pSeq->elements;
331             for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos )
332             {
333                 pElements[nPos] = createEmptySequence();
334             }
335         }
336 		break;
337 	}
338 	case typelib_TypeClass_INTERFACE: // either C++ or C-UNO interface
339 		if (nAlloc >= 0)
340             pSeq = reallocSeq( pSeq, sizeof(void *), nAlloc );
341         if (pSeq != 0)
342         {
343             ::rtl_zeroMemory(
344                 pSeq->elements + (sizeof(void *) * nStartIndex),
345                 sizeof(void *) * (nStopIndex - nStartIndex) );
346         }
347 		break;
348     default:
349 		OSL_ENSURE( 0, "### unexpected element type!" );
350         pSeq = 0;
351 		break;
352 	}
353 
354     if (pSeq == 0)
355     {
356         OSL_ASSERT( nAlloc >= 0 ); // must have been an allocation failure
357         return false;
358     }
359     else
360     {
361         *ppSeq = pSeq;
362         return true;
363     }
364 }
365 
366 //------------------------------------------------------------------------------
icopyConstructFromElements(uno_Sequence ** ppSeq,void * pSourceElements,typelib_TypeDescriptionReference * pElementType,sal_Int32 nStartIndex,sal_Int32 nStopIndex,uno_AcquireFunc acquire,sal_Int32 nAlloc=-1)367 static inline bool icopyConstructFromElements(
368 	uno_Sequence ** ppSeq, void * pSourceElements,
369 	typelib_TypeDescriptionReference * pElementType,
370 	sal_Int32 nStartIndex, sal_Int32 nStopIndex,
371 	uno_AcquireFunc acquire,
372 	sal_Int32 nAlloc = -1 ) // >= 0 means (re)alloc memory for nAlloc elements
373 {
374     uno_Sequence * pSeq = *ppSeq;
375 	switch (pElementType->eTypeClass)
376 	{
377 	case typelib_TypeClass_CHAR:
378 		if (nAlloc >= 0)
379             pSeq = reallocSeq( pSeq, sizeof(sal_Unicode), nAlloc );
380         if (pSeq != 0)
381         {
382             ::rtl_copyMemory(
383                 pSeq->elements + (sizeof(sal_Unicode) * nStartIndex),
384                 (char *)pSourceElements + (sizeof(sal_Unicode) * nStartIndex),
385                 sizeof(sal_Unicode) * (nStopIndex - nStartIndex) );
386         }
387 		break;
388 	case typelib_TypeClass_BOOLEAN:
389 		if (nAlloc >= 0)
390             pSeq = reallocSeq( pSeq, sizeof(sal_Bool), nAlloc );
391         if (pSeq != 0)
392         {
393             ::rtl_copyMemory(
394                 pSeq->elements + (sizeof(sal_Bool) * nStartIndex),
395                 (char *)pSourceElements + (sizeof(sal_Bool) * nStartIndex),
396                 sizeof(sal_Bool) * (nStopIndex - nStartIndex) );
397         }
398 		break;
399 	case typelib_TypeClass_BYTE:
400 		if (nAlloc >= 0)
401             pSeq = reallocSeq( pSeq, sizeof(sal_Int8), nAlloc );
402         if (pSeq != 0)
403         {
404             ::rtl_copyMemory(
405                 pSeq->elements + (sizeof(sal_Int8) * nStartIndex),
406                 (char *)pSourceElements + (sizeof(sal_Int8) * nStartIndex),
407                 sizeof(sal_Int8) * (nStopIndex - nStartIndex) );
408         }
409 		break;
410 	case typelib_TypeClass_SHORT:
411 	case typelib_TypeClass_UNSIGNED_SHORT:
412 		if (nAlloc >= 0)
413             pSeq = reallocSeq( pSeq, sizeof(sal_Int16), nAlloc );
414         if (pSeq != 0)
415         {
416             ::rtl_copyMemory(
417                 pSeq->elements + (sizeof(sal_Int16) * nStartIndex),
418                 (char *)pSourceElements + (sizeof(sal_Int16) * nStartIndex),
419                 sizeof(sal_Int16) * (nStopIndex - nStartIndex) );
420         }
421 		break;
422 	case typelib_TypeClass_LONG:
423 	case typelib_TypeClass_UNSIGNED_LONG:
424 		if (nAlloc >= 0)
425             pSeq = reallocSeq( pSeq, sizeof(sal_Int32), nAlloc );
426         if (pSeq != 0)
427         {
428             ::rtl_copyMemory(
429                 pSeq->elements + (sizeof(sal_Int32) * nStartIndex),
430                 (char *)pSourceElements + (sizeof(sal_Int32) * nStartIndex),
431                 sizeof(sal_Int32) * (nStopIndex - nStartIndex) );
432         }
433 		break;
434 	case typelib_TypeClass_HYPER:
435 	case typelib_TypeClass_UNSIGNED_HYPER:
436 		if (nAlloc >= 0)
437             pSeq = reallocSeq( pSeq, sizeof(sal_Int64), nAlloc );
438         if (pSeq != 0)
439         {
440             ::rtl_copyMemory(
441                 pSeq->elements + (sizeof(sal_Int64) * nStartIndex),
442                 (char *)pSourceElements + (sizeof(sal_Int64) * nStartIndex),
443                 sizeof(sal_Int64) * (nStopIndex - nStartIndex) );
444         }
445 		break;
446 	case typelib_TypeClass_FLOAT:
447 		if (nAlloc >= 0)
448             pSeq = reallocSeq( pSeq, sizeof(float), nAlloc );
449         if (pSeq != 0)
450         {
451             ::rtl_copyMemory(
452                 pSeq->elements + (sizeof(float) * nStartIndex),
453                 (char *)pSourceElements + (sizeof(float) * nStartIndex),
454                 sizeof(float) * (nStopIndex - nStartIndex) );
455         }
456 		break;
457 	case typelib_TypeClass_DOUBLE:
458 		if (nAlloc >= 0)
459             pSeq = reallocSeq( pSeq, sizeof(double), nAlloc );
460         if (pSeq != 0)
461         {
462             ::rtl_copyMemory(
463                 pSeq->elements + (sizeof(double) * nStartIndex),
464                 (char *)pSourceElements + (sizeof(double) * nStartIndex),
465                 sizeof(double) * (nStopIndex - nStartIndex) );
466         }
467 		break;
468 	case typelib_TypeClass_ENUM:
469 		if (nAlloc >= 0)
470             pSeq = reallocSeq( pSeq, sizeof(sal_Int32), nAlloc );
471         if (pSeq != 0)
472         {
473             ::rtl_copyMemory(
474                 pSeq->elements + (sizeof(sal_Int32) * nStartIndex),
475                 (char *)pSourceElements + (sizeof(sal_Int32) * nStartIndex),
476                 sizeof(sal_Int32) * (nStopIndex - nStartIndex) );
477         }
478 		break;
479 	case typelib_TypeClass_STRING:
480 	{
481 		if (nAlloc >= 0)
482             pSeq = reallocSeq( pSeq, sizeof(rtl_uString *), nAlloc );
483         if (pSeq != 0)
484         {
485             rtl_uString ** pDestElements = (rtl_uString **) pSeq->elements;
486             for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos )
487             {
488                 ::rtl_uString_acquire(
489                     ((rtl_uString **)pSourceElements)[nPos] );
490                 pDestElements[nPos] = ((rtl_uString **)pSourceElements)[nPos];
491             }
492         }
493 		break;
494 	}
495 	case typelib_TypeClass_TYPE:
496 	{
497 		if (nAlloc >= 0)
498         {
499             pSeq = reallocSeq(
500                 pSeq, sizeof(typelib_TypeDescriptionReference *), nAlloc );
501         }
502         if (pSeq != 0)
503         {
504             typelib_TypeDescriptionReference ** pDestElements =
505                 (typelib_TypeDescriptionReference **) pSeq->elements;
506             for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos )
507             {
508                 TYPE_ACQUIRE(
509                     ((typelib_TypeDescriptionReference **)
510                      pSourceElements)[nPos] );
511                 pDestElements[nPos] =
512                     ((typelib_TypeDescriptionReference **)
513                      pSourceElements)[nPos];
514             }
515 		}
516 		break;
517 	}
518 	case typelib_TypeClass_ANY:
519 	{
520 		if (nAlloc >= 0)
521             pSeq = reallocSeq( pSeq, sizeof(uno_Any), nAlloc );
522         if (pSeq != 0)
523         {
524             uno_Any * pDestElements = (uno_Any *) pSeq->elements;
525             for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos )
526             {
527                 uno_Any * pSource = (uno_Any *)pSourceElements + nPos;
528                 _copyConstructAny(
529                     &pDestElements[nPos],
530                     pSource->pData,
531                     pSource->pType, 0,
532                     acquire, 0 );
533             }
534         }
535 		break;
536 	}
537 	case typelib_TypeClass_STRUCT:
538 	case typelib_TypeClass_EXCEPTION:
539 	{
540 		typelib_TypeDescription * pElementTypeDescr = 0;
541 		TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType );
542 		sal_Int32 nElementSize = pElementTypeDescr->nSize;
543 
544 		if (nAlloc >= 0)
545             pSeq = reallocSeq( pSeq, nElementSize, nAlloc );
546         if (pSeq != 0)
547         {
548             char * pDestElements = pSeq->elements;
549 
550             typelib_CompoundTypeDescription * pTypeDescr =
551                 (typelib_CompoundTypeDescription *)pElementTypeDescr;
552             for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos )
553             {
554                 char * pDest =
555                     pDestElements + (nElementSize * nPos);
556                 char * pSource =
557                     (char *)pSourceElements + (nElementSize * nPos);
558 
559                 if (pTypeDescr->pBaseTypeDescription)
560                 {
561                     // copy base value
562                     _copyConstructStruct(
563                         pDest, pSource,
564                         pTypeDescr->pBaseTypeDescription, acquire, 0 );
565                 }
566 
567                 // then copy members
568                 typelib_TypeDescriptionReference ** ppTypeRefs =
569                     pTypeDescr->ppTypeRefs;
570                 sal_Int32 * pMemberOffsets = pTypeDescr->pMemberOffsets;
571                 sal_Int32 nDescr = pTypeDescr->nMembers;
572 
573                 while (nDescr--)
574                 {
575                     ::uno_type_copyData(
576                         pDest + pMemberOffsets[nDescr],
577                         pSource + pMemberOffsets[nDescr],
578                         ppTypeRefs[nDescr], acquire );
579                 }
580             }
581 		}
582 
583 		TYPELIB_DANGER_RELEASE( pElementTypeDescr );
584 		break;
585 	}
586 	case typelib_TypeClass_UNION:
587 	{
588 		typelib_TypeDescription * pElementTypeDescr = 0;
589 		TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType );
590 		sal_Int32 nElementSize = pElementTypeDescr->nSize;
591 
592 		if (nAlloc >= 0)
593             pSeq = reallocSeq( pSeq, nElementSize, nAlloc );
594         if (pSeq != 0)
595         {
596             char * pDestElements = pSeq->elements;
597 
598             sal_Int32 nValueOffset =
599                 ((typelib_UnionTypeDescription *)
600                  pElementTypeDescr)->nValueOffset;
601             for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos )
602             {
603                 char * pDest =
604                     pDestElements + (nElementSize * nPos);
605                 char * pSource =
606                     (char *)pSourceElements + (nElementSize * nPos);
607 
608                 typelib_TypeDescriptionReference * pSetType = _unionGetSetType(
609                     pSource, pElementTypeDescr );
610                 ::uno_type_copyData(
611                     pDest + nValueOffset,
612                     pSource + nValueOffset,
613                     pSetType, acquire );
614                 *(sal_Int64 *)pDest = *(sal_Int64 *)pSource;
615                 typelib_typedescriptionreference_release( pSetType );
616             }
617         }
618 
619 		TYPELIB_DANGER_RELEASE( pElementTypeDescr );
620 		break;
621 	}
622 	case typelib_TypeClass_SEQUENCE: // sequence of sequence
623 	{
624 		if (nAlloc >= 0)
625             pSeq = reallocSeq( pSeq, sizeof(uno_Sequence *), nAlloc );
626         if (pSeq != 0)
627         {
628             typelib_TypeDescription * pElementTypeDescr = 0;
629             TYPELIB_DANGER_GET( &pElementTypeDescr, pElementType );
630             typelib_TypeDescriptionReference * pSeqElementType =
631                 ((typelib_IndirectTypeDescription *) pElementTypeDescr)->pType;
632             uno_Sequence ** pDestElements = (uno_Sequence **) pSeq->elements;
633             for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos )
634             {
635                 uno_Sequence * pNew = icopyConstructSequence(
636                     ((uno_Sequence **) pSourceElements)[nPos],
637                     pSeqElementType, acquire, 0 );
638                 OSL_ASSERT( pNew != 0 );
639                 // ought never be a memory allocation problem,
640                 // because of reference counted sequence handles
641                 pDestElements[ nPos ] = pNew;
642             }
643             TYPELIB_DANGER_RELEASE( pElementTypeDescr );
644         }
645 		break;
646 	}
647 	case typelib_TypeClass_INTERFACE:
648 	{
649 		if (nAlloc >= 0)
650             pSeq = reallocSeq( pSeq, sizeof(void *), nAlloc );
651         if (pSeq != 0)
652         {
653             void ** pDestElements = (void **) pSeq->elements;
654             for ( sal_Int32 nPos = nStartIndex; nPos < nStopIndex; ++nPos )
655             {
656                 _acquire( pDestElements[nPos] =
657                           ((void **)pSourceElements)[nPos], acquire );
658             }
659         }
660 		break;
661 	}
662     default:
663 		OSL_ENSURE( 0, "### unexpected element type!" );
664         pSeq = 0;
665 		break;
666 	}
667 
668     if (pSeq == 0)
669     {
670         OSL_ASSERT( nAlloc >= 0 ); // must have been an allocation failure
671         return false;
672     }
673     else
674     {
675         *ppSeq = pSeq;
676         return true;
677     }
678 }
679 
680 //------------------------------------------------------------------------------
ireallocSequence(uno_Sequence ** ppSequence,typelib_TypeDescriptionReference * pElementType,sal_Int32 nSize,uno_AcquireFunc acquire,uno_ReleaseFunc release)681 static inline bool ireallocSequence(
682 	uno_Sequence ** ppSequence,
683 	typelib_TypeDescriptionReference * pElementType,
684 	sal_Int32 nSize,
685 	uno_AcquireFunc acquire, uno_ReleaseFunc release )
686 {
687     bool ret = true;
688 	uno_Sequence * pSeq = *ppSequence;
689 	sal_Int32 nElements = pSeq->nElements;
690 
691 	if (pSeq->nRefCount > 1 ||
692         // not mem-copyable elements?
693         typelib_TypeClass_ANY == pElementType->eTypeClass ||
694         typelib_TypeClass_STRUCT == pElementType->eTypeClass ||
695         typelib_TypeClass_EXCEPTION == pElementType->eTypeClass)
696 	{
697         // split sequence and construct new one from scratch
698 		uno_Sequence * pNew = 0;
699 
700 		sal_Int32 nRest = nSize - nElements;
701 		sal_Int32 nCopy = (nRest > 0 ? nElements : nSize);
702 
703 		if (nCopy >= 0)
704 		{
705 			ret = icopyConstructFromElements(
706 				&pNew, pSeq->elements, pElementType,
707 				0, nCopy, acquire,
708 				nSize ); // alloc to nSize
709 		}
710 		if (ret && nRest > 0)
711 		{
712 			ret = idefaultConstructElements(
713 				&pNew, pElementType,
714 				nCopy, nSize,
715 				nCopy >= 0 ? -1 /* no mem allocation */ : nSize );
716 		}
717 
718         if (ret)
719         {
720             // destruct sequence
721             if (osl_decrementInterlockedCount( &pSeq->nRefCount ) == 0)
722             {
723                 if (nElements > 0)
724                 {
725                     idestructElements(
726                         pSeq->elements, pElementType,
727                         0, nElements, release );
728                 }
729                 rtl_freeMemory( pSeq );
730             }
731             *ppSequence = pNew;
732         }
733 	}
734 	else
735 	{
736         OSL_ASSERT( pSeq->nRefCount == 1 );
737         if (nSize > nElements) // default construct the rest
738         {
739             ret = idefaultConstructElements(
740                 ppSequence, pElementType,
741                 nElements, nSize,
742                 nSize ); // realloc to nSize
743         }
744         else // or destruct the rest and realloc mem
745         {
746             sal_Int32 nElementSize = idestructElements(
747                 pSeq->elements, pElementType,
748                 nSize, nElements, release );
749             // warning: it is assumed that the following will never fail,
750             //          else this leads to a sequence null handle
751             *ppSequence = reallocSeq( pSeq, nElementSize, nSize );
752             OSL_ASSERT( *ppSequence != 0 );
753             ret = (*ppSequence != 0);
754         }
755 	}
756 
757     return ret;
758 }
759 
760 }
761 
762 extern "C"
763 {
764 
765 //##############################################################################
uno_type_sequence_construct(uno_Sequence ** ppSequence,typelib_TypeDescriptionReference * pType,void * pElements,sal_Int32 len,uno_AcquireFunc acquire)766 sal_Bool SAL_CALL uno_type_sequence_construct(
767 	uno_Sequence ** ppSequence, typelib_TypeDescriptionReference * pType,
768 	void * pElements, sal_Int32 len,
769 	uno_AcquireFunc acquire )
770 	SAL_THROW_EXTERN_C()
771 {
772     bool ret;
773 	if (len)
774 	{
775 		typelib_TypeDescription * pTypeDescr = 0;
776 		TYPELIB_DANGER_GET( &pTypeDescr, pType );
777 
778 		typelib_TypeDescriptionReference * pElementType =
779 			((typelib_IndirectTypeDescription *)pTypeDescr)->pType;
780 
781         *ppSequence = 0;
782 		if (pElements == 0)
783 		{
784 			ret = idefaultConstructElements(
785 				ppSequence, pElementType,
786 				0, len,
787 				len ); // alloc to len
788 		}
789 		else
790 		{
791 			ret = icopyConstructFromElements(
792 				ppSequence, pElements, pElementType,
793 				0, len, acquire,
794 				len ); // alloc to len
795 		}
796 
797 		TYPELIB_DANGER_RELEASE( pTypeDescr );
798 	}
799 	else
800 	{
801 		*ppSequence = createEmptySequence();
802         ret = true;
803 	}
804 
805     OSL_ASSERT( (*ppSequence != 0) == ret );
806     return ret;
807 }
808 
809 //##############################################################################
uno_sequence_construct(uno_Sequence ** ppSequence,typelib_TypeDescription * pTypeDescr,void * pElements,sal_Int32 len,uno_AcquireFunc acquire)810 sal_Bool SAL_CALL uno_sequence_construct(
811 	uno_Sequence ** ppSequence, typelib_TypeDescription * pTypeDescr,
812 	void * pElements, sal_Int32 len,
813 	uno_AcquireFunc acquire )
814 	SAL_THROW_EXTERN_C()
815 {
816     bool ret;
817 	if (len > 0)
818 	{
819 		typelib_TypeDescriptionReference * pElementType =
820 			((typelib_IndirectTypeDescription *)pTypeDescr)->pType;
821 
822         *ppSequence = 0;
823 		if (pElements == 0)
824 		{
825 			ret = idefaultConstructElements(
826 				ppSequence, pElementType,
827 				0, len,
828 				len ); // alloc to len
829 		}
830 		else
831 		{
832 			ret = icopyConstructFromElements(
833 				ppSequence, pElements, pElementType,
834 				0, len, acquire,
835 				len ); // alloc to len
836 		}
837 	}
838 	else
839 	{
840 		*ppSequence = createEmptySequence();
841         ret = true;
842 	}
843 
844     OSL_ASSERT( (*ppSequence != 0) == ret );
845     return ret;
846 }
847 
848 //##############################################################################
uno_type_sequence_realloc(uno_Sequence ** ppSequence,typelib_TypeDescriptionReference * pType,sal_Int32 nSize,uno_AcquireFunc acquire,uno_ReleaseFunc release)849 sal_Bool SAL_CALL uno_type_sequence_realloc(
850 	uno_Sequence ** ppSequence, typelib_TypeDescriptionReference * pType,
851     sal_Int32 nSize, uno_AcquireFunc acquire, uno_ReleaseFunc release )
852 	SAL_THROW_EXTERN_C()
853 {
854 	OSL_ENSURE( ppSequence, "### null ptr!" );
855 	OSL_ENSURE( nSize >= 0, "### new size must be at least 0!" );
856 
857     bool ret = true;
858 	if (nSize != (*ppSequence)->nElements)
859 	{
860 		typelib_TypeDescription * pTypeDescr = 0;
861 		TYPELIB_DANGER_GET( &pTypeDescr, pType );
862 		ret = ireallocSequence(
863 			ppSequence, ((typelib_IndirectTypeDescription *)pTypeDescr)->pType,
864 			nSize, acquire, release );
865 		TYPELIB_DANGER_RELEASE( pTypeDescr );
866 	}
867     return ret;
868 }
869 
870 //##############################################################################
uno_sequence_realloc(uno_Sequence ** ppSequence,typelib_TypeDescription * pTypeDescr,sal_Int32 nSize,uno_AcquireFunc acquire,uno_ReleaseFunc release)871 sal_Bool SAL_CALL uno_sequence_realloc(
872 	uno_Sequence ** ppSequence, typelib_TypeDescription * pTypeDescr,
873     sal_Int32 nSize, uno_AcquireFunc acquire, uno_ReleaseFunc release )
874 	SAL_THROW_EXTERN_C()
875 {
876 	OSL_ENSURE( ppSequence, "### null ptr!" );
877 	OSL_ENSURE( nSize >= 0, "### new size must be at least 0!" );
878 
879     bool ret = true;
880 	if (nSize != (*ppSequence)->nElements)
881 	{
882 		ret = ireallocSequence(
883 			ppSequence, ((typelib_IndirectTypeDescription *)pTypeDescr)->pType,
884 			nSize, acquire, release );
885 	}
886     return ret;
887 }
888 
889 //##############################################################################
uno_type_sequence_reference2One(uno_Sequence ** ppSequence,typelib_TypeDescriptionReference * pType,uno_AcquireFunc acquire,uno_ReleaseFunc release)890 sal_Bool SAL_CALL uno_type_sequence_reference2One(
891 	uno_Sequence ** ppSequence,
892 	typelib_TypeDescriptionReference * pType,
893 	uno_AcquireFunc acquire, uno_ReleaseFunc release )
894 	SAL_THROW_EXTERN_C()
895 {
896 	OSL_ENSURE( ppSequence, "### null ptr!" );
897     bool ret = true;
898 	uno_Sequence * pSequence = *ppSequence;
899 	if (pSequence->nRefCount > 1)
900 	{
901         uno_Sequence * pNew = 0;
902 		if (pSequence->nElements > 0)
903 		{
904 			typelib_TypeDescription * pTypeDescr = 0;
905 			TYPELIB_DANGER_GET( &pTypeDescr, pType );
906 
907 			ret = icopyConstructFromElements(
908 				&pNew, pSequence->elements,
909 				((typelib_IndirectTypeDescription *)pTypeDescr)->pType,
910 				0, pSequence->nElements, acquire,
911 				pSequence->nElements ); // alloc nElements
912             if (ret)
913             {
914                 idestructSequence( *ppSequence, pType, pTypeDescr, release );
915                 *ppSequence = pNew;
916             }
917 
918 			TYPELIB_DANGER_RELEASE( pTypeDescr );
919 		}
920 		else
921 		{
922 			pNew = allocSeq( 0, 0 );
923             ret = (pNew != 0);
924             if (ret)
925             {
926                 // easy destruction of empty sequence:
927                 if (osl_decrementInterlockedCount( &pSequence->nRefCount ) == 0)
928                     rtl_freeMemory( pSequence );
929                 *ppSequence = pNew;
930             }
931 		}
932 	}
933     return ret;
934 }
935 
936 //##############################################################################
uno_sequence_reference2One(uno_Sequence ** ppSequence,typelib_TypeDescription * pTypeDescr,uno_AcquireFunc acquire,uno_ReleaseFunc release)937 sal_Bool SAL_CALL uno_sequence_reference2One(
938 	uno_Sequence ** ppSequence,
939 	typelib_TypeDescription * pTypeDescr,
940 	uno_AcquireFunc acquire, uno_ReleaseFunc release )
941 	SAL_THROW_EXTERN_C()
942 {
943 	OSL_ENSURE( ppSequence, "### null ptr!" );
944     bool ret = true;
945 	uno_Sequence * pSequence = *ppSequence;
946 	if (pSequence->nRefCount > 1)
947 	{
948         uno_Sequence * pNew = 0;
949 		if (pSequence->nElements > 0)
950 		{
951 			ret = icopyConstructFromElements(
952 				&pNew, pSequence->elements,
953 				((typelib_IndirectTypeDescription *)pTypeDescr)->pType,
954 				0, pSequence->nElements, acquire,
955 				pSequence->nElements ); // alloc nElements
956             if (ret)
957             {
958                 idestructSequence(
959                     pSequence, pTypeDescr->pWeakRef, pTypeDescr, release );
960                 *ppSequence = pNew;
961             }
962         }
963         else
964         {
965 			pNew = allocSeq( 0, 0 );
966             ret = (pNew != 0);
967             if (ret)
968             {
969                 // easy destruction of empty sequence:
970                 if (osl_decrementInterlockedCount( &pSequence->nRefCount ) == 0)
971                     rtl_freeMemory( pSequence );
972                 *ppSequence = pNew;
973             }
974         }
975 
976 	}
977     return ret;
978 }
979 
980 //##############################################################################
uno_sequence_assign(uno_Sequence ** ppDest,uno_Sequence * pSource,typelib_TypeDescription * pTypeDescr,uno_ReleaseFunc release)981 void SAL_CALL uno_sequence_assign(
982 	uno_Sequence ** ppDest,
983 	uno_Sequence * pSource,
984 	typelib_TypeDescription * pTypeDescr,
985 	uno_ReleaseFunc release )
986 	SAL_THROW_EXTERN_C()
987 {
988 	if (*ppDest != pSource)
989 	{
990 		::osl_incrementInterlockedCount( &pSource->nRefCount );
991 		idestructSequence( *ppDest, pTypeDescr->pWeakRef, pTypeDescr, release );
992 		*ppDest = pSource;
993 	}
994 }
995 
996 //##############################################################################
uno_type_sequence_assign(uno_Sequence ** ppDest,uno_Sequence * pSource,typelib_TypeDescriptionReference * pType,uno_ReleaseFunc release)997 void SAL_CALL uno_type_sequence_assign(
998 	uno_Sequence ** ppDest,
999 	uno_Sequence * pSource,
1000 	typelib_TypeDescriptionReference * pType,
1001 	uno_ReleaseFunc release )
1002 	SAL_THROW_EXTERN_C()
1003 {
1004 	if (*ppDest != pSource)
1005 	{
1006 		::osl_incrementInterlockedCount( &pSource->nRefCount );
1007 		idestructSequence( *ppDest, pType, 0, release );
1008 		*ppDest = pSource;
1009 	}
1010 }
1011 
1012 }
1013