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: sbxarray.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_basic.hxx"
33 #include <tools/stream.hxx>
34 #include <basic/sbx.hxx>
35 #include "runtime.hxx"
39 struct SbxDim
{ // eine Array-Dimension:
40 SbxDim
* pNext
; // Link
41 INT32 nLbound
, nUbound
; // Begrenzungen
42 INT32 nSize
; // Anzahl Elemente
45 class SbxVarEntry
: public SbxVariableRef
{
48 SbxVarEntry() : SbxVariableRef(), pAlias( NULL
) {}
49 ~SbxVarEntry() { delete pAlias
; }
52 typedef SbxVarEntry
* SbxVarEntryPtr
;
53 typedef vector
< SbxVarEntryPtr
> SbxVarEntryPtrVector
;
54 class SbxVarRefs
: public SbxVarEntryPtrVector
61 TYPEINIT1(SbxArray
,SbxBase
)
62 TYPEINIT1(SbxDimArray
,SbxArray
)
64 //////////////////////////////////////////////////////////////////////////
68 //////////////////////////////////////////////////////////////////////////
70 SbxArray::SbxArray( SbxDataType t
) : SbxBase()
72 pData
= new SbxVarRefs
;
78 SbxArray::SbxArray( const SbxArray
& rArray
) :
79 SvRefBase( rArray
), SbxBase()
81 pData
= new SbxVarRefs
;
82 if( rArray
.eType
!= SbxVARIANT
)
87 SbxArray
& SbxArray::operator=( const SbxArray
& rArray
)
93 SbxVarRefs
* pSrc
= rArray
.pData
;
94 for( UINT32 i
= 0; i
< pSrc
->size(); i
++ )
96 SbxVarEntryPtr pSrcRef
= (*pSrc
)[i
];
97 const SbxVariable
* pSrc_
= *pSrcRef
;
100 SbxVarEntryPtr pDstRef
= new SbxVarEntry
;
101 *((SbxVariableRef
*) pDstRef
) = *((SbxVariableRef
*) pSrcRef
);
102 if( pSrcRef
->pAlias
)
103 pDstRef
->pAlias
= new XubString( *pSrcRef
->pAlias
);
104 if( eType
!= SbxVARIANT
)
105 // Keine Objekte konvertieren
106 if( eType
!= SbxOBJECT
|| pSrc_
->GetClass() != SbxCLASS_OBJECT
)
107 ((SbxVariable
*) pSrc_
)->Convert( eType
);
108 pData
->push_back( pDstRef
);
114 SbxArray::~SbxArray()
120 SbxDataType
SbxArray::GetType() const
122 return (SbxDataType
) ( eType
| SbxARRAY
);
125 SbxClassType
SbxArray::GetClass() const
127 return SbxCLASS_ARRAY
;
130 void SbxArray::Clear()
132 UINT32 nSize
= pData
->size();
133 for( UINT32 i
= 0 ; i
< nSize
; i
++ )
135 SbxVarEntry
* pEntry
= (*pData
)[i
];
141 UINT32
SbxArray::Count32() const
143 return pData
->size();
146 USHORT
SbxArray::Count() const
148 UINT32 nCount
= pData
->size();
149 DBG_ASSERT( nCount
<= SBX_MAXINDEX
, "SBX: Array-Index > SBX_MAXINDEX" );
150 return (USHORT
)nCount
;
153 SbxVariableRef
& SbxArray::GetRef32( UINT32 nIdx
)
155 // Array ggf. vergroessern
156 DBG_ASSERT( nIdx
<= SBX_MAXINDEX32
, "SBX: Array-Index > SBX_MAXINDEX32" );
158 if( nIdx
> SBX_MAXINDEX32
)
160 SetError( SbxERR_BOUNDS
);
163 while( pData
->size() <= nIdx
)
165 const SbxVarEntryPtr p
= new SbxVarEntry
;
166 pData
->push_back( p
);
168 return *((*pData
)[nIdx
]);
171 SbxVariableRef
& SbxArray::GetRef( USHORT nIdx
)
173 // Array ggf. vergroessern
174 DBG_ASSERT( nIdx
<= SBX_MAXINDEX
, "SBX: Array-Index > SBX_MAXINDEX" );
176 if( nIdx
> SBX_MAXINDEX
)
178 SetError( SbxERR_BOUNDS
);
181 while( pData
->size() <= nIdx
)
183 const SbxVarEntryPtr p
= new SbxVarEntry
;
184 pData
->push_back( p
);
186 return *((*pData
)[nIdx
]);
189 SbxVariable
* SbxArray::Get32( UINT32 nIdx
)
193 SetError( SbxERR_PROP_WRITEONLY
);
196 SbxVariableRef
& rRef
= GetRef32( nIdx
);
199 rRef
= new SbxVariable( eType
);
202 DBG_CHKOBJ( rRef
, SbxBase
, 0 );
208 SbxVariable
* SbxArray::Get( USHORT nIdx
)
212 SetError( SbxERR_PROP_WRITEONLY
);
215 SbxVariableRef
& rRef
= GetRef( nIdx
);
218 rRef
= new SbxVariable( eType
);
221 DBG_CHKOBJ( rRef
, SbxBase
, 0 );
227 void SbxArray::Put32( SbxVariable
* pVar
, UINT32 nIdx
)
230 SetError( SbxERR_PROP_READONLY
);
234 if( eType
!= SbxVARIANT
)
235 // Keine Objekte konvertieren
236 if( eType
!= SbxOBJECT
|| pVar
->GetClass() != SbxCLASS_OBJECT
)
237 pVar
->Convert( eType
);
238 SbxVariableRef
& rRef
= GetRef32( nIdx
);
239 if( (SbxVariable
*) rRef
!= pVar
)
242 SetFlag( SBX_MODIFIED
);
247 void SbxArray::Put( SbxVariable
* pVar
, USHORT nIdx
)
250 SetError( SbxERR_PROP_READONLY
);
254 if( eType
!= SbxVARIANT
)
255 // Keine Objekte konvertieren
256 if( eType
!= SbxOBJECT
|| pVar
->GetClass() != SbxCLASS_OBJECT
)
257 pVar
->Convert( eType
);
258 SbxVariableRef
& rRef
= GetRef( nIdx
);
259 if( (SbxVariable
*) rRef
!= pVar
)
262 SetFlag( SBX_MODIFIED
);
267 const XubString
& SbxArray::GetAlias( USHORT nIdx
)
271 SetError( SbxERR_PROP_WRITEONLY
);
272 return String::EmptyString();
274 SbxVarEntry
& rRef
= (SbxVarEntry
&) GetRef( nIdx
);
277 return String::EmptyString();
280 DBG_CHKOBJ( rRef
, SbxBase
, 0 );
286 void SbxArray::PutAlias( const XubString
& rAlias
, USHORT nIdx
)
289 SetError( SbxERR_PROP_READONLY
);
292 SbxVarEntry
& rRef
= (SbxVarEntry
&) GetRef( nIdx
);
294 rRef
.pAlias
= new XubString( rAlias
);
296 *rRef
.pAlias
= rAlias
;
300 void SbxArray::Insert32( SbxVariable
* pVar
, UINT32 nIdx
)
302 DBG_ASSERT( pData
->size() <= SBX_MAXINDEX32
, "SBX: Array wird zu gross" );
303 if( pData
->size() > SBX_MAXINDEX32
)
305 SbxVarEntryPtr p
= new SbxVarEntry
;
306 *((SbxVariableRef
*) p
) = pVar
;
307 SbxVarEntryPtrVector::size_type nSize
= pData
->size();
310 if( eType
!= SbxVARIANT
&& pVar
)
311 (*p
)->Convert( eType
);
314 pData
->push_back( p
);
318 pData
->insert( pData
->begin() + nIdx
, p
);
320 SetFlag( SBX_MODIFIED
);
323 void SbxArray::Insert( SbxVariable
* pVar
, USHORT nIdx
)
325 DBG_ASSERT( pData
->size() <= 0x3FF0, "SBX: Array wird zu gross" );
326 if( pData
->size() > 0x3FF0 )
328 Insert32( pVar
, nIdx
);
331 void SbxArray::Remove32( UINT32 nIdx
)
333 if( nIdx
< pData
->size() )
335 SbxVariableRef
* pRef
= (*pData
)[nIdx
];
336 pData
->erase( pData
->begin() + nIdx
);
338 SetFlag( SBX_MODIFIED
);
342 void SbxArray::Remove( USHORT nIdx
)
344 if( nIdx
< pData
->size() )
346 SbxVariableRef
* pRef
= (*pData
)[nIdx
];
347 pData
->erase( pData
->begin() + nIdx
);
349 SetFlag( SBX_MODIFIED
);
353 void SbxArray::Remove( SbxVariable
* pVar
)
357 for( UINT32 i
= 0; i
< pData
->size(); i
++ )
359 SbxVariableRef
* pRef
= (*pData
)[i
];
360 // SbxVariableRef* pRef = pData->GetObject( i );
363 Remove32( i
); break;
369 // Uebernahme der Daten aus dem uebergebenen Array, wobei
370 // gleichnamige Variable ueberschrieben werden.
372 void SbxArray::Merge( SbxArray
* p
)
376 UINT32 nSize
= p
->Count();
377 for( UINT32 i
= 0; i
< nSize
; i
++ )
379 SbxVarEntryPtr pRef1
= (*(p
->pData
))[i
];
380 // Ist das Element by name schon drin?
381 // Dann ueberschreiben!
382 SbxVariable
* pVar
= *pRef1
;
385 XubString aName
= pVar
->GetName();
386 USHORT nHash
= pVar
->GetHashCode();
387 for( UINT32 j
= 0; j
< pData
->size(); j
++ )
389 SbxVariableRef
* pRef2
= (*pData
)[j
];
390 if( (*pRef2
)->GetHashCode() == nHash
391 && (*pRef2
)->GetName().EqualsIgnoreCaseAscii( aName
) )
393 *pRef2
= pVar
; pRef1
= NULL
;
399 SbxVarEntryPtr pRef
= new SbxVarEntry
;
400 const SbxVarEntryPtr pTemp
= pRef
;
401 pData
->push_back( pTemp
);
402 *((SbxVariableRef
*) pRef
) = *((SbxVariableRef
*) pRef1
);
404 pRef
->pAlias
= new XubString( *pRef1
->pAlias
);
411 // Suchen eines Elements ueber die Userdaten. Falls ein Element
412 // ein Objekt ist, wird dieses ebenfalls durchsucht.
414 SbxVariable
* SbxArray::FindUserData( UINT32 nData
)
416 SbxVariable
* p
= NULL
;
417 for( UINT32 i
= 0; i
< pData
->size(); i
++ )
419 SbxVariableRef
* pRef
= (*pData
)[i
];
420 SbxVariable
* pVar
= *pRef
;
423 if( pVar
->IsVisible() && pVar
->GetUserData() == nData
)
426 p
->ResetFlag( SBX_EXTFOUND
);
427 break; // JSM 06.10.95
429 // Haben wir ein Array/Objekt mit Extended Search?
430 else if( pVar
->IsSet( SBX_EXTSEARCH
) )
432 switch( pVar
->GetClass() )
434 case SbxCLASS_OBJECT
:
436 // Objekte duerfen ihren Parent nicht durchsuchen
437 USHORT nOld
= pVar
->GetFlags();
438 pVar
->ResetFlag( SBX_GBLSEARCH
);
439 p
= ((SbxObject
*) pVar
)->FindUserData( nData
);
440 pVar
->SetFlags( nOld
);
444 p
= ((SbxArray
*) pVar
)->FindUserData( nData
);
450 p
->SetFlag( SBX_EXTFOUND
);
459 // Suchen eines Elements ueber den Namen und den Typ. Falls ein Element
460 // ein Objekt ist, wird dieses ebenfalls durchsucht.
462 SbxVariable
* SbxArray::Find( const XubString
& rName
, SbxClassType t
)
464 SbxVariable
* p
= NULL
;
465 UINT32 nCount
= pData
->size();
468 BOOL bExtSearch
= IsSet( SBX_EXTSEARCH
);
469 USHORT nHash
= SbxVariable::MakeHashCode( rName
);
470 for( UINT32 i
= 0; i
< nCount
; i
++ )
472 SbxVariableRef
* pRef
= (*pData
)[i
];
473 SbxVariable
* pVar
= *pRef
;
474 if( pVar
&& pVar
->IsVisible() )
476 // Die ganz sichere Suche klappt auch, wenn es
477 // keinen Hascode gibt!
478 USHORT nVarHash
= pVar
->GetHashCode();
479 if( ( !nVarHash
|| nVarHash
== nHash
)
480 && ( t
== SbxCLASS_DONTCARE
|| pVar
->GetClass() == t
)
481 && ( pVar
->GetName().EqualsIgnoreCaseAscii( rName
) ) )
484 p
->ResetFlag( SBX_EXTFOUND
);
487 // Haben wir ein Array/Objekt mit Extended Search?
488 else if( bExtSearch
&& pVar
->IsSet( SBX_EXTSEARCH
) )
490 switch( pVar
->GetClass() )
492 case SbxCLASS_OBJECT
:
494 // Objekte duerfen ihren Parent nicht durchsuchen
495 USHORT nOld
= pVar
->GetFlags();
496 pVar
->ResetFlag( SBX_GBLSEARCH
);
497 p
= ((SbxObject
*) pVar
)->Find( rName
, t
);
498 pVar
->SetFlags( nOld
);
502 p
= ((SbxArray
*) pVar
)->Find( rName
, t
);
508 p
->SetFlag( SBX_EXTFOUND
);
517 BOOL
SbxArray::LoadData( SvStream
& rStrm
, USHORT nVer
)
526 for( UINT32 n
= 0; n
< nElem
; n
++ )
530 SbxVariable
* pVar
= (SbxVariable
*) Load( rStrm
);
533 SbxVariableRef
& rRef
= GetRef( nIdx
);
542 bRes
= LoadPrivateData( rStrm
, nVer
);
547 BOOL
SbxArray::StoreData( SvStream
& rStrm
) const
551 // Welche Elemente sind ueberhaupt definiert?
552 for( n
= 0; n
< pData
->size(); n
++ )
554 SbxVariableRef
* pRef
= (*pData
)[n
];
555 SbxVariable
* p
= *pRef
;
556 if( p
&& !( p
->GetFlags() & SBX_DONTSTORE
) )
559 rStrm
<< (UINT16
) nElem
;
560 for( n
= 0; n
< pData
->size(); n
++ )
562 SbxVariableRef
* pRef
= (*pData
)[n
];
563 SbxVariable
* p
= *pRef
;
564 if( p
&& !( p
->GetFlags() & SBX_DONTSTORE
) )
567 if( !p
->Store( rStrm
) )
571 return StorePrivateData( rStrm
);
574 // #100883 Method to set method directly to parameter array
575 void SbxArray::PutDirect( SbxVariable
* pVar
, UINT32 nIdx
)
577 SbxVariableRef
& rRef
= GetRef32( nIdx
);
582 //////////////////////////////////////////////////////////////////////////
586 //////////////////////////////////////////////////////////////////////////
588 SbxDimArray::SbxDimArray( SbxDataType t
) : SbxArray( t
), mbHasFixedSize( false )
590 pFirst
= pLast
= NULL
;
594 SbxDimArray::SbxDimArray( const SbxDimArray
& rArray
)
595 : SvRefBase( rArray
), SbxArray( rArray
.eType
)
597 pFirst
= pLast
= NULL
;
602 SbxDimArray
& SbxDimArray::operator=( const SbxDimArray
& rArray
)
604 if( &rArray
!= this )
606 SbxArray::operator=( (const SbxArray
&) rArray
);
607 SbxDim
* p
= rArray
.pFirst
;
610 AddDim32( p
->nLbound
, p
->nUbound
);
613 this->mbHasFixedSize
= rArray
.mbHasFixedSize
;
618 SbxDimArray::~SbxDimArray()
623 void SbxDimArray::Clear()
628 SbxDim
* q
= p
->pNext
;
632 pFirst
= pLast
= NULL
;
636 // Dimension hinzufuegen
638 void SbxDimArray::AddDimImpl32( INT32 lb
, INT32 ub
, BOOL bAllowSize0
)
640 SbxError eRes
= SbxERR_OK
;
641 if( ub
< lb
&& !bAllowSize0
)
643 eRes
= SbxERR_BOUNDS
;
646 SbxDim
* p
= new SbxDim
;
649 p
->nSize
= ub
- lb
+ 1;
654 pLast
->pNext
= p
, pLast
= p
;
660 void SbxDimArray::AddDim( short lb
, short ub
)
662 AddDimImpl32( lb
, ub
, FALSE
);
665 void SbxDimArray::unoAddDim( short lb
, short ub
)
667 AddDimImpl32( lb
, ub
, TRUE
);
670 void SbxDimArray::AddDim32( INT32 lb
, INT32 ub
)
672 AddDimImpl32( lb
, ub
, FALSE
);
675 void SbxDimArray::unoAddDim32( INT32 lb
, INT32 ub
)
677 AddDimImpl32( lb
, ub
, TRUE
);
681 // Dimensionsdaten auslesen
683 BOOL
SbxDimArray::GetDim32( INT32 n
, INT32
& rlb
, INT32
& rub
) const
685 if( n
< 1 || n
> nDim
)
687 SetError( SbxERR_BOUNDS
); rub
= rlb
= 0; return FALSE
;
697 BOOL
SbxDimArray::GetDim( short n
, short& rlb
, short& rub
) const
700 BOOL bRet
= GetDim32( n
, rlb32
, rub32
);
703 if( rlb32
< -SBX_MAXINDEX
|| rub32
> SBX_MAXINDEX
)
705 SetError( SbxERR_BOUNDS
);
714 // Element-Ptr anhand einer Index-Liste
716 UINT32
SbxDimArray::Offset32( const INT32
* pIdx
)
719 for( SbxDim
* p
= pFirst
; p
; p
= p
->pNext
)
721 INT32 nIdx
= *pIdx
++;
722 if( nIdx
< p
->nLbound
|| nIdx
> p
->nUbound
)
724 nPos
= (UINT32
)SBX_MAXINDEX32
+ 1; break;
726 nPos
= nPos
* p
->nSize
+ nIdx
- p
->nLbound
;
728 if( nDim
== 0 || nPos
> SBX_MAXINDEX32
)
730 SetError( SbxERR_BOUNDS
); nPos
= 0;
735 USHORT
SbxDimArray::Offset( const short* pIdx
)
738 for( SbxDim
* p
= pFirst
; p
; p
= p
->pNext
)
740 short nIdx
= *pIdx
++;
741 if( nIdx
< p
->nLbound
|| nIdx
> p
->nUbound
)
743 nPos
= SBX_MAXINDEX
+ 1; break;
745 nPos
= nPos
* p
->nSize
+ nIdx
- p
->nLbound
;
747 if( nDim
== 0 || nPos
> SBX_MAXINDEX
)
749 SetError( SbxERR_BOUNDS
); nPos
= 0;
751 return (USHORT
) nPos
;
754 SbxVariableRef
& SbxDimArray::GetRef( const short* pIdx
)
756 return SbxArray::GetRef( Offset( pIdx
) );
759 SbxVariable
* SbxDimArray::Get( const short* pIdx
)
761 return SbxArray::Get( Offset( pIdx
) );
764 void SbxDimArray::Put( SbxVariable
* p
, const short* pIdx
)
766 SbxArray::Put( p
, Offset( pIdx
) );
769 SbxVariableRef
& SbxDimArray::GetRef32( const INT32
* pIdx
)
771 return SbxArray::GetRef32( Offset32( pIdx
) );
774 SbxVariable
* SbxDimArray::Get32( const INT32
* pIdx
)
776 return SbxArray::Get32( Offset32( pIdx
) );
779 void SbxDimArray::Put32( SbxVariable
* p
, const INT32
* pIdx
)
781 SbxArray::Put32( p
, Offset32( pIdx
) );
785 // Element-Nr anhand eines Parameter-Arrays
787 UINT32
SbxDimArray::Offset32( SbxArray
* pPar
)
789 if( nDim
== 0 || !pPar
|| ( ( nDim
!= ( pPar
->Count() - 1 ) ) && SbiRuntime::isVBAEnabled() ) )
791 SetError( SbxERR_BOUNDS
); return 0;
794 USHORT nOff
= 1; // Nicht Element 0!
795 for( SbxDim
* p
= pFirst
; p
&& !IsError(); p
= p
->pNext
)
797 INT32 nIdx
= pPar
->Get( nOff
++ )->GetLong();
798 if( nIdx
< p
->nLbound
|| nIdx
> p
->nUbound
)
800 nPos
= (UINT32
) SBX_MAXINDEX32
+1; break;
802 nPos
= nPos
* p
->nSize
+ nIdx
- p
->nLbound
;
804 if( nPos
> (UINT32
) SBX_MAXINDEX32
)
806 SetError( SbxERR_BOUNDS
); nPos
= 0;
811 USHORT
SbxDimArray::Offset( SbxArray
* pPar
)
813 UINT32 nPos
= Offset32( pPar
);
814 if( nPos
> (long) SBX_MAXINDEX
)
816 SetError( SbxERR_BOUNDS
); nPos
= 0;
818 return (USHORT
) nPos
;
821 SbxVariableRef
& SbxDimArray::GetRef( SbxArray
* pPar
)
823 return SbxArray::GetRef32( Offset32( pPar
) );
826 SbxVariable
* SbxDimArray::Get( SbxArray
* pPar
)
828 return SbxArray::Get32( Offset32( pPar
) );
831 void SbxDimArray::Put( SbxVariable
* p
, SbxArray
* pPar
)
833 SbxArray::Put32( p
, Offset32( pPar
) );
836 BOOL
SbxDimArray::LoadData( SvStream
& rStrm
, USHORT nVer
)
840 for( short i
= 0; i
< nDimension
&& rStrm
.GetError() == SVSTREAM_OK
; i
++ )
846 return SbxArray::LoadData( rStrm
, nVer
);
849 BOOL
SbxDimArray::StoreData( SvStream
& rStrm
) const
851 rStrm
<< (INT16
) nDim
;
852 for( short i
= 0; i
< nDim
; i
++ )
856 rStrm
<< (INT16
) lb
<< (INT16
) ub
;
858 return SbxArray::StoreData( rStrm
);