update dev300-m58
[ooovba.git] / sc / inc / compressedarray.hxx
blobf9b8b621253b8a48b6364103342201c72613abc2
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
35 #include <cstddef>
36 #define INCLUDED_CSTDDEF
37 #endif
39 #ifndef INCLUDED_ALGORITHM
40 #include <algorithm>
41 #define INCLUDED_ALGORITHM
42 #endif
43 #include "scdllapi.h"
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
58 struct or class.
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
64 Resize() if needed.
67 template< typename A, typename D > class ScCompressedArray
69 public:
70 struct DataEntry
72 A nEnd; // start is end of previous entry + 1
73 D aValue;
74 DataEntry() {} //! uninitialized
77 /** Construct with nMaxAccess=MAXROW, for example. */
78 ScCompressedArray( A nMaxAccess,
79 const D& rValue,
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;
130 protected:
132 friend class ScCompressedArrayIterator<A,D>;
134 size_t nCount;
135 size_t nLimit;
136 size_t nDelta;
137 DataEntry* pData;
138 A nMaxAccess;
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.
147 D aTmpVal( rValue);
148 delete[] pData;
149 nCount = nLimit = 1;
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,
182 A& nEnd ) const
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
194 if (nIndex < nCount)
195 ++nIndex;
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
205 if (nIndex > 0)
206 --nIndex;
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
215 return nCount;
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
243 public:
244 ScCompressedArrayIterator(
245 const ScCompressedArray<A,D> & rArray,
246 A nStart, A nEnd );
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).
252 bool operator ++();
253 A GetPos() const;
254 operator bool() const;
255 const D& operator *() const;
256 /// Advance an entire range, one entry of the array.
257 bool NextRange();
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
264 iterator bounds. */
265 template< typename X >
266 void Follow( const ScCompressedArrayIterator<A,X>& );
268 private:
269 const ScCompressedArray<A,D> & rArray;
270 size_t nIndex;
271 A nIterStart;
272 A nIterEnd;
273 A nCurrent;
274 bool bEnd;
278 template< typename A, typename D >
279 ScCompressedArrayIterator<A,D>::ScCompressedArrayIterator(
280 const ScCompressedArray<A,D> & rArrayP, A nStart, A nEnd )
281 : rArray( rArrayP )
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 )
291 nIterStart = nStart;
292 nIterEnd = 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
302 return nIterStart;
306 template< typename A, typename D >
307 A ScCompressedArrayIterator<A,D>::GetIterEnd() const
309 return nIterEnd;
313 template< typename A, typename D >
314 bool ScCompressedArrayIterator<A,D>::operator++()
316 if (nCurrent < GetRangeEnd())
318 ++nCurrent;
319 return true;
321 else
322 return NextRange();
326 template< typename A, typename D >
327 A ScCompressedArrayIterator<A,D>::GetPos() const
329 return nCurrent;
333 template< typename A, typename D >
334 bool ScCompressedArrayIterator<A,D>::NextRange()
336 if (!operator bool())
337 return false;
339 if (rArray.pData[nIndex].nEnd >= nIterEnd)
340 bEnd = true;
341 else if (++nIndex >= rArray.GetEntryCount())
343 nIndex = rArray.GetEntryCount() - 1;
344 bEnd = true;
346 nCurrent = bEnd ? nIterEnd : GetRangeStart();
347 return operator bool();
351 template< typename A, typename D >
352 ScCompressedArrayIterator<A,D>::operator bool() const
354 return !bEnd;
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
368 if (nIndex == 0)
369 return nIterStart > 0 ? nIterStart : 0;
370 else
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)
388 nPos = nIterStart;
389 else if (nPos > nIterEnd)
390 nPos = nIterEnd;
391 nCurrent = nPos;
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>
406 public:
407 ScSummableCompressedArray( A nMaxAccessP,
408 const D& rValue,
409 size_t nDeltaP = nScCompressedArrayDelta )
410 : ScCompressedArray<A,D>( nMaxAccessP,
411 rValue, nDeltaP)
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>
449 public:
450 ScBitMaskCompressedArray( A nMaxAccessP,
451 const D& rValue,
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. */
466 void CopyFromAnded(
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. */
472 void CopyFromOred(
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()
492 is returned. */
493 SC_DLLPUBLIC A GetFirstForCondition( A nStart, A nEnd,
494 const D& rBitMask,
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()
500 is returned. */
501 SC_DLLPUBLIC A GetLastForCondition( A nStart, A nEnd,
502 const D& rBitMask,
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,
508 const D& rBitMask,
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,
514 const D& rBitMask,
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,
521 const D& rBitMask,
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
580 public:
581 SC_DLLPUBLIC ScCoupledCompressedArrayIterator(
582 const ScBitMaskCompressedArray<A,D> & rArray1,
583 A nStart, A nEnd,
584 const D& rBitMask,
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;
590 bool operator ++();
591 A GetPos() 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 );
599 private:
600 ScCompressedArrayIterator<A,D> aIter1;
601 ScCompressedArrayIterator<A,S> aIter2;
602 const D& rBitMask;
603 const D& rMaskedCompare;
605 void InitLimits();
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
633 return *aIter2;
637 template< typename A, typename D, typename S >
638 bool ScCoupledCompressedArrayIterator<A,D,S>::operator ++()
640 if (aIter1.GetPos() < aIter1.GetRangeEnd())
642 ++aIter1;
643 ++aIter2;
644 return operator bool();
646 else
647 return NextRange();
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