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: compressedarray.hxx,v $
10 * $Revision: 1.7.32.2 $
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 #ifndef SC_COMPRESSEDARRAY_HXX
32 #define SC_COMPRESSEDARRAY_HXX
34 #ifndef INCLUDED_CSTDDEF
36 #define INCLUDED_CSTDDEF
39 #ifndef INCLUDED_ALGORITHM
41 #define INCLUDED_ALGORITHM
45 const size_t nScCompressedArrayDelta
= 4;
47 template< typename A
, typename D
> class ScCompressedArrayIterator
;
49 /** Compressed array of row (or column) entries, e.g. heights, flags, ...
51 The array stores ranges of values such that consecutive values occupy only
52 one entry. Initially it consists of one DataEntry with an implied start
53 row/column of 0 and an end row/column of access type maximum value.
55 typename A := access type, e.g. SCROW or SCCOL, must be a POD.
57 typename D := data type, e.g. USHORT or BYTE or whatever, may also be a
60 D::operator==() and D::operator=() must be implemented. Force template
61 instantiation for a specific type in source/core/data/compressedarray.cxx
63 TODO: Currently the allocated memory never shrinks, must manually invoke
67 template< typename A
, typename D
> class ScCompressedArray
72 A nEnd
; // start is end of previous entry + 1
74 DataEntry() {} //! uninitialized
77 /** Construct with nMaxAccess=MAXROW, for example. */
78 ScCompressedArray( A nMaxAccess
,
80 size_t nDelta
= nScCompressedArrayDelta
);
81 /** Construct from a plain array of D */
82 ScCompressedArray( A nMaxAccess
,
83 const D
* pDataArray
, size_t nDataCount
);
84 virtual ~ScCompressedArray();
85 void Resize( size_t nNewSize
);
86 void Reset( const D
& rValue
);
87 void SetValue( A nPos
, const D
& rValue
);
88 void SetValue( A nStart
, A nEnd
, const D
& rValue
);
89 const D
& GetValue( A nPos
) const;
91 /** Get value for a row, and it's region end row */
92 const D
& GetValue( A nPos
, size_t& nIndex
, A
& nEnd
) const;
94 /** Get value for a row, and it's region start row and end row */
95 const D
& GetValue( A nPos
, size_t& nIndex
, A
& nStart
, A
& nEnd
) const;
97 /** Get next value and it's region end row. If nIndex<nCount, nIndex is
98 incremented first. If the resulting nIndex>=nCount, the value of the
99 last entry is returned again. */
100 const D
& GetNextValue( size_t& nIndex
, A
& nEnd
) const;
102 /** Get previous value and it's region start row. If nIndex==0, nIndex is
103 not decremented and the value of the first entry is returned again. */
104 const D
& GetPrevValue( size_t& nIndex
, A
& nStart
) const;
106 /** Return the last row where an entry meets the condition:
107 (aValue != rCompare). If no entry meets this condition
108 ::std::numeric_limits<A>::max() is returned. */
109 A
GetLastUnequalAccess( A nStart
, const D
& rCompare
);
111 /** Insert rows before nStart and copy value for inserted rows from
112 nStart-1, return that value. */
113 const D
& Insert( A nStart
, size_t nCount
);
115 void Remove( A nStart
, size_t nCount
);
117 /** Copy rArray.nStart+nSourceDy to this.nStart */
118 void CopyFrom( const ScCompressedArray
& rArray
,
119 A nStart
, A nEnd
, long nSourceDy
= 0 );
122 // methods public for the coupled array sum methods
123 /** Obtain index into entries for nPos */
124 SC_DLLPUBLIC
size_t Search( A nPos
) const;
125 /** Get number of entries */
126 size_t GetEntryCount() const;
127 /** Get data entry for an index */
128 const DataEntry
& GetDataEntry( size_t nIndex
) const;
132 friend class ScCompressedArrayIterator
<A
,D
>;
142 template< typename A
, typename D
>
143 void ScCompressedArray
<A
,D
>::Reset( const D
& rValue
)
145 // Create a temporary copy in case we got a reference passed that points to
146 // a part of the array to be reallocated.
150 pData
= new DataEntry
[1];
151 pData
[0].aValue
= aTmpVal
;
152 pData
[0].nEnd
= nMaxAccess
;
156 template< typename A
, typename D
>
157 void ScCompressedArray
<A
,D
>::SetValue( A nPos
, const D
& rValue
)
159 SetValue( nPos
, nPos
, rValue
);
163 template< typename A
, typename D
>
164 const D
& ScCompressedArray
<A
,D
>::GetValue( A nPos
) const
166 size_t nIndex
= Search( nPos
);
167 return pData
[nIndex
].aValue
;
171 template< typename A
, typename D
>
172 const D
& ScCompressedArray
<A
,D
>::GetValue( A nPos
, size_t& nIndex
, A
& nEnd
) const
174 nIndex
= Search( nPos
);
175 nEnd
= pData
[nIndex
].nEnd
;
176 return pData
[nIndex
].aValue
;
180 template< typename A
, typename D
>
181 const D
& ScCompressedArray
<A
,D
>::GetValue( A nPos
, size_t& nIndex
, A
& nStart
,
184 nIndex
= Search( nPos
);
185 nStart
= (nIndex
> 0 ? pData
[nIndex
-1].nEnd
+ 1 : 0);
186 nEnd
= pData
[nIndex
].nEnd
;
187 return pData
[nIndex
].aValue
;
191 template< typename A
, typename D
>
192 const D
& ScCompressedArray
<A
,D
>::GetNextValue( size_t& nIndex
, A
& nEnd
) const
196 size_t nEntry
= (nIndex
< nCount
? nIndex
: nCount
-1);
197 nEnd
= pData
[nEntry
].nEnd
;
198 return pData
[nEntry
].aValue
;
202 template< typename A
, typename D
>
203 const D
& ScCompressedArray
<A
,D
>::GetPrevValue( size_t& nIndex
, A
& nStart
) const
207 nStart
= (nIndex
> 0 ? pData
[nIndex
-1].nEnd
+ 1 : 0);
208 return pData
[nIndex
].aValue
;
212 template< typename A
, typename D
>
213 size_t ScCompressedArray
<A
,D
>::GetEntryCount() const
219 template< typename A
, typename D
>
220 const typename ScCompressedArray
<A
,D
>::DataEntry
&
221 ScCompressedArray
<A
,D
>::GetDataEntry( size_t nIndex
) const
223 return pData
[nIndex
];
227 // === ScCompressedArrayIterator =============================================
229 /** Iterator for ScCompressedArray.
231 @ATTENTION: the iterator is not persistant if the underlying
232 ScCompressedArray happens to be changed by any means, for example by
233 setting new values or adding or removing or combining entries. If you do
234 such things inside a loop you MUST resynchronize the iterator by calling
235 <method>Resync()</method> with the row where resynchronization should
236 start. After doing so, <method>GetRangeStart()</method> and
237 <method>GetRangeEnd()</method> may not point to the previous access points
238 anymore. Use with care.
241 template< typename A
, typename D
> class ScCompressedArrayIterator
244 ScCompressedArrayIterator(
245 const ScCompressedArray
<A
,D
> & rArray
,
247 /// Set new start and end, position on start.
248 void NewLimits( A nStart
, A nEnd
);
249 A
GetIterStart() const;
250 A
GetIterEnd() const;
251 /// Advance by a single access point (e.g. row).
254 operator bool() const;
255 const D
& operator *() const;
256 /// Advance an entire range, one entry of the array.
258 A
GetRangeStart() const;
259 A
GetRangeEnd() const;
260 /// Resync to underlying array, calling Search().
261 void Resync( A nPos
);
262 /** Set position without resyncing, avoid calling Search() if possible.
263 Position obtained from steering coupled iterator is NOT checked for
265 template< typename X
>
266 void Follow( const ScCompressedArrayIterator
<A
,X
>& );
269 const ScCompressedArray
<A
,D
> & rArray
;
278 template< typename A
, typename D
>
279 ScCompressedArrayIterator
<A
,D
>::ScCompressedArrayIterator(
280 const ScCompressedArray
<A
,D
> & rArrayP
, A nStart
, A nEnd
)
282 // other values set in NewLimits()
284 NewLimits( nStart
, nEnd
);
288 template< typename A
, typename D
>
289 void ScCompressedArrayIterator
<A
,D
>::NewLimits( A nStart
, A nEnd
)
293 nIndex
= rArray
.Search( nStart
);
294 nCurrent
= GetRangeStart();
295 bEnd
= (nIterEnd
< nIterStart
);
299 template< typename A
, typename D
>
300 A ScCompressedArrayIterator
<A
,D
>::GetIterStart() const
306 template< typename A
, typename D
>
307 A ScCompressedArrayIterator
<A
,D
>::GetIterEnd() const
313 template< typename A
, typename D
>
314 bool ScCompressedArrayIterator
<A
,D
>::operator++()
316 if (nCurrent
< GetRangeEnd())
326 template< typename A
, typename D
>
327 A ScCompressedArrayIterator
<A
,D
>::GetPos() const
333 template< typename A
, typename D
>
334 bool ScCompressedArrayIterator
<A
,D
>::NextRange()
336 if (!operator bool())
339 if (rArray
.pData
[nIndex
].nEnd
>= nIterEnd
)
341 else if (++nIndex
>= rArray
.GetEntryCount())
343 nIndex
= rArray
.GetEntryCount() - 1;
346 nCurrent
= bEnd
? nIterEnd
: GetRangeStart();
347 return operator bool();
351 template< typename A
, typename D
>
352 ScCompressedArrayIterator
<A
,D
>::operator bool() const
358 template< typename A
, typename D
>
359 const D
& ScCompressedArrayIterator
<A
,D
>::operator*() const
361 return rArray
.pData
[nIndex
].aValue
;
365 template< typename A
, typename D
>
366 A ScCompressedArrayIterator
<A
,D
>::GetRangeStart() const
369 return nIterStart
> 0 ? nIterStart
: 0;
371 return nIterStart
> rArray
.pData
[nIndex
-1].nEnd
? nIterStart
:
372 rArray
.pData
[nIndex
-1].nEnd
+ 1;
376 template< typename A
, typename D
>
377 A ScCompressedArrayIterator
<A
,D
>::GetRangeEnd() const
379 return nIterEnd
< rArray
.pData
[nIndex
].nEnd
? nIterEnd
:
380 rArray
.pData
[nIndex
].nEnd
;
384 template< typename A
, typename D
>
385 void ScCompressedArrayIterator
<A
,D
>::Resync( A nPos
)
387 if (nPos
< nIterStart
)
389 else if (nPos
> nIterEnd
)
392 bEnd
= (nIterEnd
< nIterStart
);
393 nIndex
= rArray
.Search( nPos
);
397 // === ScSummableCompressedArray =============================================
399 /** Data type D must be of a type that is convertable to unsigned long. The
400 advantage is that specialized methods exist to act on a region of values
401 for performance reasons.
404 template< typename A
, typename D
> class ScSummableCompressedArray
: public ScCompressedArray
<A
,D
>
407 ScSummableCompressedArray( A nMaxAccessP
,
409 size_t nDeltaP
= nScCompressedArrayDelta
)
410 : ScCompressedArray
<A
,D
>( nMaxAccessP
,
413 ScSummableCompressedArray( A nMaxAccessP
,
414 const D
* pDataArray
, size_t nDataCount
)
415 : ScCompressedArray
<A
,D
>( nMaxAccessP
,
416 pDataArray
, nDataCount
)
419 /** Returns the sum of all values for a region. If an overflow would occur,
420 ::std::numeric_limits<unsigned long>::max() is returned. */
421 unsigned long SumValues( A nStart
, A nEnd
) const;
423 /** Returns the sum of all values for a region. If an overflow would occur,
424 ::std::numeric_limits<unsigned long>::max() is returned.
425 The caller has to assure that nIndex matches an entry belonging to
426 nStart, for example, by calling Search(nStart) first! */
427 unsigned long SumValuesContinuation( A nStart
, A nEnd
,
428 size_t& nIndex
) const;
430 /** Returns the sum of all scaled values for a region. If an overflow would
431 occur, ::std::numeric_limits<unsigned long>::max() is returned.
432 Summed values are treated as if for each row the expression
433 (sum += (unsigned long) (scale * value)) had been applied.
434 The caller has to assure that nIndex matches an entry belonging to
435 nStart, for example, by calling Search(nStart) first! */
436 unsigned long SumScaledValuesContinuation( A nStart
, A nEnd
,
437 size_t& nIndex
, double fScale
) const;
442 // === ScBitMaskCompressedArray ==============================================
444 /** The data type represents bits, managable by bitwise operations.
447 template< typename A
, typename D
> class ScBitMaskCompressedArray
: public ScCompressedArray
<A
,D
>
450 ScBitMaskCompressedArray( A nMaxAccessP
,
452 size_t nDeltaP
= nScCompressedArrayDelta
)
453 : ScCompressedArray
<A
,D
>( nMaxAccessP
, rValue
, nDeltaP
)
455 ScBitMaskCompressedArray( A nMaxAccessP
,
456 const D
* pDataArray
, size_t nDataCount
)
457 : ScCompressedArray
<A
,D
>( nMaxAccessP
,
458 pDataArray
, nDataCount
)
460 void AndValue( A nPos
, const D
& rValueToAnd
);
461 void OrValue( A nPos
, const D
& rValueToOr
);
462 void AndValue( A nStart
, A nEnd
, const D
& rValueToAnd
);
463 void OrValue( A nStart
, A nEnd
, const D
& rValueToOr
);
465 /** Copy values from rArray and bitwise AND them with rValueToAnd. */
467 const ScBitMaskCompressedArray
& rArray
,
468 A nStart
, A nEnd
, const D
& rValueToAnd
,
469 long nSourceDy
= 0 );
471 /** Copy values from rArray and bitwise OR them with rValueToOr. */
473 const ScBitMaskCompressedArray
& rArray
,
474 A nStart
, A nEnd
, const D
& rValueToOr
,
475 long nSourceDy
= 0 );
477 /** Return the start row of a region where all entries meet the condition:
478 ((aValue & rBitMask) == rMaskedCompare). If not even nEnd meets
479 this condition, ::std::numeric_limits<A>::max() is returned. */
480 A
GetBitStateStart( A nEnd
, const D
& rBitMask
,
481 const D
& rMaskedCompare
) const;
483 /** Return the end row of a region where all entries meet the condition:
484 ((aValue & rBitMask) == rMaskedCompare). If not even nStart meets
485 this condition, ::std::numeric_limits<A>::max() is returned. */
486 A
GetBitStateEnd( A nStart
, const D
& rBitMask
,
487 const D
& rMaskedCompare
) const;
489 /** Return the first row where an entry meets the condition:
490 ((aValue & rBitMask) == rMaskedCompare), searching between nStart and
491 nEnd. If no entry meets this condition, ::std::numeric_limits<A>::max()
493 SC_DLLPUBLIC A
GetFirstForCondition( A nStart
, A nEnd
,
495 const D
& rMaskedCompare
) const;
497 /** Return the last row where an entry meets the condition:
498 ((aValue & rBitMask) == rMaskedCompare), searching between nStart and
499 nEnd. If no entry meets this condition, ::std::numeric_limits<A>::max()
501 SC_DLLPUBLIC A
GetLastForCondition( A nStart
, A nEnd
,
503 const D
& rMaskedCompare
) const;
505 /** Count rows between nStart and nEnd where entries meet the condition:
506 ((aValue & rBitMask) == rMaskedCompare) */
507 A
CountForCondition( A nStart
, A nEnd
,
509 const D
& rMaskedCompare
) const;
511 /** Whether there is any entry between nStart and nEnd where the condition
512 is met: ((aValue & rBitMask) == rMaskedCompare) */
513 SC_DLLPUBLIC
bool HasCondition( A nStart
, A nEnd
,
515 const D
& rMaskedCompare
) const;
517 /** Fill an array with row numbers between nStart and nEnd where entries
518 meet the condition: ((aValue & rBitMask) == rMaskedCompare).
519 @return the count of used elements in array. */
520 size_t FillArrayForCondition( A nStart
, A nEnd
,
522 const D
& rMaskedCompare
,
523 A
* pArray
, size_t nArraySize
) const;
525 /** Count rows between nStart and nEnd where entries meet the condition:
526 ((aValue & rBitMask) != 0) */
527 A
CountForAnyBitCondition( A nStart
, A nEnd
,
528 const D
& rBitMask
) const;
530 /** Return the last row where an entry meets the condition:
531 ((aValue & rBitMask) != 0), start searching at nStart. If no entry
532 meets this condition, ::std::numeric_limits<A>::max() is returned. */
533 A
GetLastAnyBitAccess( A nStart
,
534 const D
& rBitMask
) const;
536 /** Sum values of a ScSummableCompressedArray for each row where in *this*
537 array the condition is met: ((aValue & rBitMask) == rMaskedCompare). */
538 template< typename S
>
539 SC_DLLPUBLIC
unsigned long SumCoupledArrayForCondition( A nStart
, A nEnd
,
540 const D
& rBitMask
, const D
& rMaskedCompare
,
541 const ScSummableCompressedArray
<A
,S
>& rArray
) const;
543 /** Sum scaled values of a ScSummableCompressedArray for each row where in
544 *this* array the condition is met: ((aValue & rBitMask) == rMaskedCompare). */
545 template< typename S
>
546 SC_DLLPUBLIC
unsigned long SumScaledCoupledArrayForCondition( A nStart
, A nEnd
,
547 const D
& rBitMask
, const D
& rMaskedCompare
,
548 const ScSummableCompressedArray
<A
,S
>& rArray
,
549 double fScale
) const;
553 template< typename A
, typename D
>
554 void ScBitMaskCompressedArray
<A
,D
>::AndValue( A nPos
, const D
& rValueToAnd
)
556 const D
& rValue
= GetValue( nPos
);
557 if ((rValue
& rValueToAnd
) != rValue
)
558 SetValue( nPos
, rValue
& rValueToAnd
);
562 template< typename A
, typename D
>
563 void ScBitMaskCompressedArray
<A
,D
>::OrValue( A nPos
, const D
& rValueToOr
)
565 const D
& rValue
= GetValue( nPos
);
566 if ((rValue
| rValueToOr
) != rValue
)
567 SetValue( nPos
, rValue
| rValueToOr
);
571 // === ScCoupledCompressedArrayIterator ======================================
573 /** Iterate over a ScBitMaskCompressedArray and retrieve values from a coupled
574 array for positions where in the bit mask array the condition ((*aIter1 &
575 rBitMask) == rMaskedCompare) is met.
578 template< typename A
, typename D
, typename S
> class ScCoupledCompressedArrayIterator
581 SC_DLLPUBLIC
ScCoupledCompressedArrayIterator(
582 const ScBitMaskCompressedArray
<A
,D
> & rArray1
,
585 const D
& rMaskedCompare
,
586 const ScCompressedArray
<A
,S
> & rArray2
);
587 void NewLimits( A nStart
, A nEnd
);
588 A
GetIterStart() const;
589 A
GetIterEnd() const;
592 operator bool() const;
593 const S
& operator *() const;
594 SC_DLLPUBLIC
bool NextRange();
595 A
GetRangeStart() const;
596 A
GetRangeEnd() const;
597 void Resync( A nPos
);
600 ScCompressedArrayIterator
<A
,D
> aIter1
;
601 ScCompressedArrayIterator
<A
,S
> aIter2
;
603 const D
& rMaskedCompare
;
609 template< typename A
, typename D
, typename S
>
610 A ScCoupledCompressedArrayIterator
<A
,D
,S
>::GetIterStart() const
612 return aIter1
.GetIterStart();
616 template< typename A
, typename D
, typename S
>
617 A ScCoupledCompressedArrayIterator
<A
,D
,S
>::GetIterEnd() const
619 return aIter1
.GetIterEnd();
623 template< typename A
, typename D
, typename S
>
624 ScCoupledCompressedArrayIterator
<A
,D
,S
>::operator bool() const
626 return aIter1
&& aIter2
;
630 template< typename A
, typename D
, typename S
>
631 const S
& ScCoupledCompressedArrayIterator
<A
,D
,S
>::operator*() const
637 template< typename A
, typename D
, typename S
>
638 bool ScCoupledCompressedArrayIterator
<A
,D
,S
>::operator ++()
640 if (aIter1
.GetPos() < aIter1
.GetRangeEnd())
644 return operator bool();
651 template< typename A
, typename D
, typename S
>
652 A ScCoupledCompressedArrayIterator
<A
,D
,S
>::GetPos() const
654 return aIter2
.GetPos();
658 template< typename A
, typename D
, typename S
>
659 A ScCoupledCompressedArrayIterator
<A
,D
,S
>::GetRangeStart() const
661 return ::std::max( aIter1
.GetRangeStart(), aIter2
.GetRangeStart());
665 template< typename A
, typename D
, typename S
>
666 A ScCoupledCompressedArrayIterator
<A
,D
,S
>::GetRangeEnd() const
668 return ::std::min( aIter1
.GetRangeEnd(), aIter2
.GetRangeEnd());
672 #endif // SC_COMPRESSEDARRAY_HXX