update dev300-m58
[ooovba.git] / agg / inc / agg_array.h
blob2881344ba31e2ccce8668b939adb6f6ccf60ba3b
1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.3
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
4 //
5 // Permission to copy, use, modify, sell and distribute this software
6 // is granted provided this copyright notice appears in all copies.
7 // This software is provided "as is" without express or implied
8 // warranty, and with no claim as to its suitability for any purpose.
9 //
10 //----------------------------------------------------------------------------
11 // Contact: mcseem@antigrain.com
12 // mcseemagg@yahoo.com
13 // http://www.antigrain.com
14 //----------------------------------------------------------------------------
15 #ifndef AGG_ARRAY_INCLUDED
16 #define AGG_ARRAY_INCLUDED
18 #include <stddef.h>
19 #include <string.h>
20 #include "agg_basics.h"
22 namespace agg
27 //-------------------------------------------------------pod_array_adaptor
28 template<class T> class pod_array_adaptor
30 public:
31 typedef T value_type;
32 pod_array_adaptor(T* array, unsigned _size) :
33 m_array(array), m_size(_size) {}
35 unsigned size() const { return m_size; }
36 const T& operator [] (unsigned idx) const { return m_array[idx]; }
37 T& operator [] (unsigned idx) { return m_array[idx]; }
38 private:
39 T* m_array;
40 unsigned m_size;
45 //---------------------------------------------------------pod_auto_array
46 template<class T, unsigned Size> class pod_auto_array
48 public:
49 typedef T value_type;
50 typedef pod_auto_array<T, Size> self_type;
52 pod_auto_array() {}
53 explicit pod_auto_array(const T* c)
55 memcpy(m_array, c, sizeof(T) * Size);
58 const self_type& operator = (const T* c)
60 memcpy(m_array, c, sizeof(T) * Size);
61 return *this;
64 static unsigned size() { return Size; }
65 const T& operator [] (unsigned i) const { return m_array[i]; }
66 T& operator [] (unsigned i) { return m_array[i]; }
67 private:
68 T m_array[Size];
75 //---------------------------------------------------------------pod_array
76 // A simple class template to store Plain Old Data, a vector
77 // of a fixed size. The data is continous in memory
78 //------------------------------------------------------------------------
79 template<class T> class pod_array
81 public:
82 typedef T value_type;
84 ~pod_array() { delete [] m_array; }
85 pod_array() : m_size(0), m_capacity(0), m_array(0) {}
86 pod_array(unsigned cap, unsigned extra_tail=0);
88 // Copying
89 pod_array(const pod_array<T>&);
90 const pod_array<T>& operator = (const pod_array<T>&);
92 unsigned capacity() const { return m_capacity; }
93 void capacity(unsigned cap, unsigned extra_tail=0);
95 void resize(unsigned new_size);
97 void add(const T& v) { m_array[m_size++] = v; }
98 void inc_size(unsigned _size) { m_size += _size; }
99 unsigned size() const { return m_size; }
100 unsigned byte_size() const { return m_size * sizeof(T); }
101 void serialize(int8u* ptr) const;
102 void deserialize(const int8u* data, unsigned byte_size);
103 const T& operator [] (unsigned idx) const { return m_array[idx]; }
104 T& operator [] (unsigned idx) { return m_array[idx]; }
106 void remove_all() { m_size = 0; }
107 void cut_at(unsigned num) { if(num < m_size) m_size = num; }
109 private:
110 unsigned m_size;
111 unsigned m_capacity;
112 T* m_array;
115 //------------------------------------------------------------------------
116 template<class T>
117 void pod_array<T>::capacity(unsigned cap, unsigned extra_tail)
119 m_size = 0;
120 if(cap > m_capacity)
122 delete [] m_array;
123 m_capacity = cap + extra_tail;
124 m_array = m_capacity ? new T [m_capacity] : 0;
128 //------------------------------------------------------------------------
129 template<class T>
130 void pod_array<T>::resize(unsigned new_size)
132 if(new_size > m_size)
134 if(new_size > m_capacity)
136 T* data = new T[new_size];
137 memcpy(data, m_array, m_size * sizeof(T));
138 delete [] m_array;
139 m_array = data;
142 else
144 m_size = new_size;
148 //------------------------------------------------------------------------
149 template<class T> pod_array<T>::pod_array(unsigned cap, unsigned extra_tail) :
150 m_size(cap), m_capacity(cap + extra_tail), m_array(new T[m_capacity]) {}
152 //------------------------------------------------------------------------
153 template<class T> pod_array<T>::pod_array(const pod_array<T>& v) :
154 m_size(v.m_size),
155 m_capacity(v.m_capacity),
156 m_array(v.m_capacity ? new T [v.m_capacity] : 0)
158 memcpy(m_array, v.m_array, sizeof(T) * v.m_size);
161 //------------------------------------------------------------------------
162 template<class T> const pod_array<T>&
163 pod_array<T>::operator = (const pod_array<T>&v)
165 capacity(v.m_capacity);
166 if(v.m_size) memcpy(m_array, v.m_array, sizeof(T) * v.m_size);
167 return *this;
170 //------------------------------------------------------------------------
171 template<class T> void pod_array<T>::serialize(int8u* ptr) const
173 if(m_size) memcpy(ptr, m_array, m_size * sizeof(T));
176 //------------------------------------------------------------------------
177 template<class T>
178 void pod_array<T>::deserialize(const int8u* data, unsigned _byte_size)
180 _byte_size /= sizeof(T);
181 capacity(_byte_size);
182 if(_byte_size) memcpy(m_array, data, _byte_size * sizeof(T));
189 //---------------------------------------------------------------pod_deque
190 // A simple class template to store Plain Old Data, similar to std::deque
191 // It doesn't reallocate memory but instead, uses blocks of data of size
192 // of (1 << S), that is, power of two. The data is NOT contiguous in memory,
193 // so the only valid access method is operator [] or curr(), prev(), next()
195 // There reallocs occure only when the pool of pointers to blocks needs
196 // to be extended (it happens very rarely). You can control the value
197 // of increment to reallocate the pointer buffer. See the second constructor.
198 // By default, the incremeent value equals (1 << S), i.e., the block size.
199 //------------------------------------------------------------------------
200 template<class T, unsigned S=6> class pod_deque
202 public:
203 enum
205 block_shift = S,
206 block_size = 1 << block_shift,
207 block_mask = block_size - 1
210 typedef T value_type;
212 ~pod_deque();
213 pod_deque();
214 pod_deque(unsigned block_ptr_inc);
216 // Copying
217 pod_deque(const pod_deque<T, S>& v);
218 const pod_deque<T, S>& operator = (const pod_deque<T, S>& v);
220 void remove_all() { m_size = 0; }
221 void free_all() { free_tail(0); }
222 void free_tail(unsigned size);
223 void add(const T& val);
224 void modify_last(const T& val);
225 void remove_last();
227 int allocate_continuous_block(unsigned num_elements);
229 void add_array(const T* ptr, unsigned num_elem)
231 while(num_elem--)
233 add(*ptr++);
237 template<class DataAccessor> void add_data(DataAccessor& data)
239 while(data.size())
241 add(*data);
242 ++data;
246 void cut_at(unsigned _size)
248 if(_size < m_size) m_size = _size;
251 unsigned size() const { return m_size; }
253 const T& operator [] (unsigned idx) const
255 return m_blocks[idx >> block_shift][idx & block_mask];
258 T& operator [] (unsigned idx)
260 return m_blocks[idx >> block_shift][idx & block_mask];
263 const T& curr(unsigned idx) const
265 return (*this)[idx];
268 T& curr(unsigned idx)
270 return (*this)[idx];
273 const T& prev(unsigned idx) const
275 return (*this)[(idx + m_size - 1) % m_size];
278 T& prev(unsigned idx)
280 return (*this)[(idx + m_size - 1) % m_size];
283 const T& next(unsigned idx) const
285 return (*this)[(idx + 1) % m_size];
288 T& next(unsigned idx)
290 return (*this)[(idx + 1) % m_size];
293 const T& last() const
295 return (*this)[m_size - 1];
298 T& last()
300 return (*this)[m_size - 1];
303 unsigned byte_size() const;
304 void serialize(int8u* ptr) const;
305 void deserialize(const int8u* data, unsigned byte_size);
306 void deserialize(unsigned start, const T& empty_val,
307 const int8u* data, unsigned byte_size);
309 template<class ByteAccessor>
310 void deserialize(ByteAccessor data)
312 remove_all();
313 unsigned elem_size = data.size() / sizeof(T);
315 for(unsigned i = 0; i < elem_size; ++i)
317 int8u* ptr = (int8u*)data_ptr();
318 for(unsigned j = 0; j < sizeof(T); ++j)
320 *ptr++ = *data;
321 ++data;
323 ++m_size;
327 template<class ByteAccessor>
328 void deserialize(unsigned start, const T& empty_val, ByteAccessor data)
330 while(m_size < start)
332 add(empty_val);
335 unsigned elem_size = data.size() / sizeof(T);
336 for(unsigned i = 0; i < elem_size; ++i)
338 int8u* ptr;
339 if(start + i < m_size)
341 ptr = (int8u*)(&((*this)[start + i]));
343 else
345 ptr = (int8u*)data_ptr();
346 ++m_size;
348 for(unsigned j = 0; j < sizeof(T); ++j)
350 *ptr++ = *data;
351 ++data;
356 const T* block(unsigned nb) const { return m_blocks[nb]; }
358 private:
359 void allocate_block(unsigned nb);
360 T* data_ptr();
362 unsigned m_size;
363 unsigned m_num_blocks;
364 unsigned m_max_blocks;
365 T** m_blocks;
366 unsigned m_block_ptr_inc;
370 //------------------------------------------------------------------------
371 template<class T, unsigned S> pod_deque<T, S>::~pod_deque()
373 if(m_num_blocks)
375 T** blk = m_blocks + m_num_blocks - 1;
376 while(m_num_blocks--)
378 delete [] *blk;
379 --blk;
381 delete [] m_blocks;
386 //------------------------------------------------------------------------
387 template<class T, unsigned S>
388 void pod_deque<T, S>::free_tail(unsigned _size)
390 if(_size < m_size)
392 unsigned nb = (_size + block_mask) >> block_shift;
393 while(m_num_blocks > nb)
395 delete [] m_blocks[--m_num_blocks];
397 m_size = _size;
402 //------------------------------------------------------------------------
403 template<class T, unsigned S> pod_deque<T, S>::pod_deque() :
404 m_size(0),
405 m_num_blocks(0),
406 m_max_blocks(0),
407 m_blocks(0),
408 m_block_ptr_inc(block_size)
413 //------------------------------------------------------------------------
414 template<class T, unsigned S>
415 pod_deque<T, S>::pod_deque(unsigned block_ptr_inc) :
416 m_size(0),
417 m_num_blocks(0),
418 m_max_blocks(0),
419 m_blocks(0),
420 m_block_ptr_inc(block_ptr_inc)
425 //------------------------------------------------------------------------
426 template<class T, unsigned S>
427 pod_deque<T, S>::pod_deque(const pod_deque<T, S>& v) :
428 m_size(v.m_size),
429 m_num_blocks(v.m_num_blocks),
430 m_max_blocks(v.m_max_blocks),
431 m_blocks(v.m_max_blocks ? new T* [v.m_max_blocks] : 0),
432 m_block_ptr_inc(v.m_block_ptr_inc)
434 unsigned i;
435 for(i = 0; i < v.m_num_blocks; ++i)
437 m_blocks[i] = new T [block_size];
438 memcpy(m_blocks[i], v.m_blocks[i], block_size * sizeof(T));
443 //------------------------------------------------------------------------
444 template<class T, unsigned S>
445 const pod_deque<T, S>& pod_deque<T, S>::operator = (const pod_deque<T, S>& v)
447 unsigned i;
448 for(i = m_num_blocks; i < v.m_num_blocks; ++i)
450 allocate_block(i);
452 for(i = 0; i < v.m_num_blocks; ++i)
454 memcpy(m_blocks[i], v.m_blocks[i], block_size * sizeof(T));
456 m_size = v.m_size;
457 return *this;
461 //------------------------------------------------------------------------
462 template<class T, unsigned S>
463 void pod_deque<T, S>::allocate_block(unsigned nb)
465 if(nb >= m_max_blocks)
467 T** new_blocks = new T* [m_max_blocks + m_block_ptr_inc];
469 if(m_blocks)
471 memcpy(new_blocks,
472 m_blocks,
473 m_num_blocks * sizeof(T*));
475 delete [] m_blocks;
477 m_blocks = new_blocks;
478 m_max_blocks += m_block_ptr_inc;
480 m_blocks[nb] = new T [block_size];
481 m_num_blocks++;
486 //------------------------------------------------------------------------
487 template<class T, unsigned S>
488 inline T* pod_deque<T, S>::data_ptr()
490 unsigned nb = m_size >> block_shift;
491 if(nb >= m_num_blocks)
493 allocate_block(nb);
495 return m_blocks[nb] + (m_size & block_mask);
500 //------------------------------------------------------------------------
501 template<class T, unsigned S>
502 inline void pod_deque<T, S>::add(const T& val)
504 *data_ptr() = val;
505 ++m_size;
509 //------------------------------------------------------------------------
510 template<class T, unsigned S>
511 inline void pod_deque<T, S>::remove_last()
513 if(m_size) --m_size;
517 //------------------------------------------------------------------------
518 template<class T, unsigned S>
519 void pod_deque<T, S>::modify_last(const T& val)
521 remove_last();
522 add(val);
526 //------------------------------------------------------------------------
527 template<class T, unsigned S>
528 int pod_deque<T, S>::allocate_continuous_block(unsigned num_elements)
530 if(num_elements < block_size)
532 data_ptr(); // Allocate initial block if necessary
533 unsigned rest = block_size - (m_size & block_mask);
534 unsigned index;
535 if(num_elements <= rest)
537 // The rest of the block is good, we can use it
538 //-----------------
539 index = m_size;
540 m_size += num_elements;
541 return index;
544 // New block
545 //---------------
546 m_size += rest;
547 data_ptr();
548 index = m_size;
549 m_size += num_elements;
550 return index;
552 return -1; // Impossible to allocate
556 //------------------------------------------------------------------------
557 template<class T, unsigned S>
558 unsigned pod_deque<T, S>::byte_size() const
560 return m_size * sizeof(T);
564 //------------------------------------------------------------------------
565 template<class T, unsigned S>
566 void pod_deque<T, S>::serialize(int8u* ptr) const
568 unsigned i;
569 for(i = 0; i < m_size; i++)
571 memcpy(ptr, &(*this)[i], sizeof(T));
572 ptr += sizeof(T);
576 //------------------------------------------------------------------------
577 template<class T, unsigned S>
578 void pod_deque<T, S>::deserialize(const int8u* data, unsigned _byte_size)
580 remove_all();
581 _byte_size /= sizeof(T);
582 for(unsigned i = 0; i < _byte_size; ++i)
584 T* ptr = data_ptr();
585 memcpy(ptr, data, sizeof(T));
586 ++m_size;
587 data += sizeof(T);
592 // Replace or add a number of elements starting from "start" position
593 //------------------------------------------------------------------------
594 template<class T, unsigned S>
595 void pod_deque<T, S>::deserialize(unsigned start, const T& empty_val,
596 const int8u* data, unsigned _byte_size)
598 while(m_size < start)
600 add(empty_val);
603 _byte_size /= sizeof(T);
604 for(unsigned i = 0; i < _byte_size; ++i)
606 if(start + i < m_size)
608 memcpy(&((*this)[start + i]), data, sizeof(T));
610 else
612 T* ptr = data_ptr();
613 memcpy(ptr, data, sizeof(T));
614 ++m_size;
616 data += sizeof(T);
621 //-----------------------------------------------------------pod_allocator
622 // Allocator for arbitrary POD data. Most usable in different cache
623 // systems for efficient memory allocations.
624 // Memory is allocated with blocks of fixed size ("block_size" in
625 // the constructor). If required size exceeds the block size the allocator
626 // creates a new block of the required size. However, the most efficient
627 // use is when the average reqired size is much less than the block size.
628 //------------------------------------------------------------------------
629 class pod_allocator
631 public:
632 void remove_all()
634 if(m_num_blocks)
636 int8u** blk = m_blocks + m_num_blocks - 1;
637 while(m_num_blocks--)
639 delete [] *blk;
640 --blk;
642 delete [] m_blocks;
644 m_num_blocks = 0;
645 m_max_blocks = 0;
646 m_blocks = 0;
647 m_buf_ptr = 0;
648 m_rest = 0;
651 ~pod_allocator()
653 remove_all();
656 pod_allocator(unsigned block_size, unsigned block_ptr_inc=256-8) :
657 m_block_size(block_size),
658 m_block_ptr_inc(block_ptr_inc),
659 m_num_blocks(0),
660 m_max_blocks(0),
661 m_blocks(0),
662 m_buf_ptr(0),
663 m_rest(0)
668 int8u* allocate(unsigned size, unsigned alignment=1)
670 if(size == 0) return 0;
671 if(size <= m_rest)
673 int8u* ptr = m_buf_ptr;
674 if(alignment > 1)
676 unsigned align = (alignment - unsigned((size_t)ptr) % alignment) % alignment;
677 size += align;
678 ptr += align;
679 if(size <= m_rest)
681 m_rest -= size;
682 m_buf_ptr += size;
683 return ptr;
685 allocate_block(size);
686 return allocate(size - align, alignment);
688 m_rest -= size;
689 m_buf_ptr += size;
690 return ptr;
692 allocate_block(size + alignment - 1);
693 return allocate(size, alignment);
697 private:
698 void allocate_block(unsigned size)
700 if(size < m_block_size) size = m_block_size;
701 if(m_num_blocks >= m_max_blocks)
703 int8u** new_blocks = new int8u* [m_max_blocks + m_block_ptr_inc];
705 if(m_blocks)
707 memcpy(new_blocks,
708 m_blocks,
709 m_num_blocks * sizeof(int8u*));
711 delete [] m_blocks;
713 m_blocks = new_blocks;
714 m_max_blocks += m_block_ptr_inc;
716 m_blocks[m_num_blocks] = m_buf_ptr = new int8u [size];
717 m_num_blocks++;
718 m_rest = size;
721 unsigned m_block_size;
722 unsigned m_block_ptr_inc;
723 unsigned m_num_blocks;
724 unsigned m_max_blocks;
725 int8u** m_blocks;
726 int8u* m_buf_ptr;
727 unsigned m_rest;
737 //------------------------------------------------------------------------
738 enum
740 quick_sort_threshold = 9
744 //-----------------------------------------------------------swap_elements
745 template<class T> inline void swap_elements(T& a, T& b)
747 T temp = a;
748 a = b;
749 b = temp;
753 //--------------------------------------------------------------quick_sort
754 template<class Array, class Less>
755 void quick_sort(Array& arr, Less less)
757 if(arr.size() < 2) return;
759 typename Array::value_type* e1;
760 typename Array::value_type* e2;
762 int stack[80];
763 int* top = stack;
764 int limit = arr.size();
765 int base = 0;
767 for(;;)
769 int len = limit - base;
771 int i;
772 int j;
773 int pivot;
775 if(len > quick_sort_threshold)
777 // we use base + len/2 as the pivot
778 pivot = base + len / 2;
779 swap_elements(arr[base], arr[pivot]);
781 i = base + 1;
782 j = limit - 1;
784 // now ensure that *i <= *base <= *j
785 e1 = &(arr[j]);
786 e2 = &(arr[i]);
787 if(less(*e1, *e2)) swap_elements(*e1, *e2);
789 e1 = &(arr[base]);
790 e2 = &(arr[i]);
791 if(less(*e1, *e2)) swap_elements(*e1, *e2);
793 e1 = &(arr[j]);
794 e2 = &(arr[base]);
795 if(less(*e1, *e2)) swap_elements(*e1, *e2);
797 for(;;)
799 do i++; while( less(arr[i], arr[base]) );
800 do j--; while( less(arr[base], arr[j]) );
802 if( i > j )
804 break;
807 swap_elements(arr[i], arr[j]);
810 swap_elements(arr[base], arr[j]);
812 // now, push the largest sub-array
813 if(j - base > limit - i)
815 top[0] = base;
816 top[1] = j;
817 base = i;
819 else
821 top[0] = i;
822 top[1] = limit;
823 limit = j;
825 top += 2;
827 else
829 // the sub-array is small, perform insertion sort
830 j = base;
831 i = j + 1;
833 for(; i < limit; j = i, i++)
835 for(; less(*(e1 = &(arr[j + 1])), *(e2 = &(arr[j]))); j--)
837 swap_elements(*e1, *e2);
838 if(j == base)
840 break;
844 if(top > stack)
846 top -= 2;
847 base = top[0];
848 limit = top[1];
850 else
852 break;
861 //------------------------------------------------------remove_duplicates
862 // Remove duplicates from a sorted array. It doesn't cut the the
863 // tail of the array, it just returns the number of remaining elements.
864 //-----------------------------------------------------------------------
865 template<class Array, class Equal>
866 unsigned remove_duplicates(Array& arr, Equal equal)
868 if(arr.size() < 2) return arr.size();
870 unsigned i, j;
871 for(i = 1, j = 1; i < arr.size(); i++)
873 typename Array::value_type& e = arr[i];
874 if(!equal(e, arr[i - 1]))
876 arr[j++] = e;
879 return j;
887 #endif