ToolMap
Loading...
Searching...
No Matches
agg_array.h
1//----------------------------------------------------------------------------
2// Anti-Grain Geometry (AGG) - Version 2.5
3// A high quality rendering engine for C++
4// Copyright (C) 2002-2006 Maxim Shemanarev
5// Contact: mcseem@antigrain.com
6// mcseemagg@yahoo.com
7// http://antigrain.com
8//
9// AGG is free software; you can redistribute it and/or
10// modify it under the terms of the GNU General Public License
11// as published by the Free Software Foundation; either version 2
12// of the License, or (at your option) any later version.
13//
14// AGG is distributed in the hope that it will be useful,
15// but WITHOUT ANY WARRANTY; without even the implied warranty of
16// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17// GNU General Public License for more details.
18//
19// You should have received a copy of the GNU General Public License
20// along with AGG; if not, write to the Free Software
21// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22// MA 02110-1301, USA.
23//----------------------------------------------------------------------------
24
25#ifndef AGG_ARRAY_INCLUDED
26#define AGG_ARRAY_INCLUDED
27
28#include <stddef.h>
29#include <string.h>
30
31#include "agg_basics.h"
32
33namespace agg {
34
35//-------------------------------------------------------pod_array_adaptor
36template <class T>
38 public:
39 typedef T value_type;
40
41 pod_array_adaptor(T* array, unsigned size)
42 : m_array(array),
43 m_size(size) {}
44
45 unsigned size() const {
46 return m_size;
47 }
48
49 const T& operator[](unsigned i) const {
50 return m_array[i];
51 }
52
53 T& operator[](unsigned i) {
54 return m_array[i];
55 }
56
57 const T& at(unsigned i) const {
58 return m_array[i];
59 }
60
61 T& at(unsigned i) {
62 return m_array[i];
63 }
64
65 T value_at(unsigned i) const {
66 return m_array[i];
67 }
68
69 private:
70 T* m_array;
71 unsigned m_size;
72};
73
74//---------------------------------------------------------pod_auto_array
75template <class T, unsigned Size>
77 public:
78 typedef T value_type;
80
82
83 explicit pod_auto_array(const T* c) {
84 memcpy(m_array, c, sizeof(T) * Size);
85 }
86
87 const self_type& operator=(const T* c) {
88 memcpy(m_array, c, sizeof(T) * Size);
89 return *this;
90 }
91
92 static unsigned size() {
93 return Size;
94 }
95
96 const T& operator[](unsigned i) const {
97 return m_array[i];
98 }
99
100 T& operator[](unsigned i) {
101 return m_array[i];
102 }
103
104 const T& at(unsigned i) const {
105 return m_array[i];
106 }
107
108 T& at(unsigned i) {
109 return m_array[i];
110 }
111
112 T value_at(unsigned i) const {
113 return m_array[i];
114 }
115
116 private:
117 T m_array[Size];
118};
119
120//--------------------------------------------------------pod_auto_vector
121template <class T, unsigned Size>
123 public:
124 typedef T value_type;
126
128 : m_size(0) {}
129
130 void remove_all() {
131 m_size = 0;
132 }
133
134 void clear() {
135 m_size = 0;
136 }
137
138 void add(const T& v) {
139 m_array[m_size++] = v;
140 }
141
142 void push_back(const T& v) {
143 m_array[m_size++] = v;
144 }
145
146 void inc_size(unsigned size) {
147 m_size += size;
148 }
149
150 unsigned size() const {
151 return m_size;
152 }
153
154 const T& operator[](unsigned i) const {
155 return m_array[i];
156 }
157
158 T& operator[](unsigned i) {
159 return m_array[i];
160 }
161
162 const T& at(unsigned i) const {
163 return m_array[i];
164 }
165
166 T& at(unsigned i) {
167 return m_array[i];
168 }
169
170 T value_at(unsigned i) const {
171 return m_array[i];
172 }
173
174 private:
175 T m_array[Size];
176 unsigned m_size;
177};
178
179//---------------------------------------------------------------pod_array
180template <class T>
182 public:
183 typedef T value_type;
184 typedef pod_array<T> self_type;
185
186 ~pod_array() {
187 pod_allocator<T>::deallocate(m_array, m_size);
188 }
189
190 pod_array()
191 : m_array(0),
192 m_size(0) {}
193
194 pod_array(unsigned size)
195 : m_array(pod_allocator<T>::allocate(size)),
196 m_size(size) {}
197
198 pod_array(const self_type& v)
199 : m_array(pod_allocator<T>::allocate(v.m_size)),
200 m_size(v.m_size) {
201 memcpy(m_array, v.m_array, sizeof(T) * m_size);
202 }
203
204 void resize(unsigned size) {
205 if (size != m_size) {
206 pod_allocator<T>::deallocate(m_array, m_size);
207 m_array = pod_allocator<T>::allocate(m_size = size);
208 }
209 }
210
211 const self_type& operator=(const self_type& v) {
212 resize(v.size());
213 memcpy(m_array, v.m_array, sizeof(T) * m_size);
214 return *this;
215 }
216
217 unsigned size() const {
218 return m_size;
219 }
220
221 const T& operator[](unsigned i) const {
222 return m_array[i];
223 }
224
225 T& operator[](unsigned i) {
226 return m_array[i];
227 }
228
229 const T& at(unsigned i) const {
230 return m_array[i];
231 }
232
233 T& at(unsigned i) {
234 return m_array[i];
235 }
236
237 T value_at(unsigned i) const {
238 return m_array[i];
239 }
240
241 const T* data() const {
242 return m_array;
243 }
244
245 T* data() {
246 return m_array;
247 }
248
249 private:
250 T* m_array;
251 unsigned m_size;
252};
253
254//--------------------------------------------------------------pod_vector
255// A simple class template to store Plain Old Data, a vector
256// of a fixed size. The data is continous in memory
257//------------------------------------------------------------------------
258template <class T>
260 public:
261 typedef T value_type;
262
263 ~pod_vector() {
264 pod_allocator<T>::deallocate(m_array, m_capacity);
265 }
266
267 pod_vector()
268 : m_size(0),
269 m_capacity(0),
270 m_array(0) {}
271
272 pod_vector(unsigned cap, unsigned extra_tail = 0);
273
274 // Copying
276
277 const pod_vector<T>& operator=(const pod_vector<T>&);
278
279 // Set new capacity. All data is lost, size is set to zero.
280 void capacity(unsigned cap, unsigned extra_tail = 0);
281
282 unsigned capacity() const {
283 return m_capacity;
284 }
285
286 // Allocate n elements. All data is lost,
287 // but elements can be accessed in range 0...size-1.
288 void allocate(unsigned size, unsigned extra_tail = 0);
289
290 // Resize keeping the content.
291 void resize(unsigned new_size);
292
293 void zero() {
294 memset(m_array, 0, sizeof(T) * m_size);
295 }
296
297 void add(const T& v) {
298 m_array[m_size++] = v;
299 }
300
301 void push_back(const T& v) {
302 m_array[m_size++] = v;
303 }
304
305 void insert_at(unsigned pos, const T& val);
306
307 void inc_size(unsigned size) {
308 m_size += size;
309 }
310
311 unsigned size() const {
312 return m_size;
313 }
314
315 unsigned byte_size() const {
316 return m_size * sizeof(T);
317 }
318
319 void serialize(int8u* ptr) const;
320
321 void deserialize(const int8u* data, unsigned byte_size);
322
323 const T& operator[](unsigned i) const {
324 return m_array[i];
325 }
326
327 T& operator[](unsigned i) {
328 return m_array[i];
329 }
330
331 const T& at(unsigned i) const {
332 return m_array[i];
333 }
334
335 T& at(unsigned i) {
336 return m_array[i];
337 }
338
339 T value_at(unsigned i) const {
340 return m_array[i];
341 }
342
343 const T* data() const {
344 return m_array;
345 }
346
347 T* data() {
348 return m_array;
349 }
350
351 void remove_all() {
352 m_size = 0;
353 }
354
355 void clear() {
356 m_size = 0;
357 }
358
359 void cut_at(unsigned num) {
360 if (num < m_size) m_size = num;
361 }
362
363 private:
364 unsigned m_size;
365 unsigned m_capacity;
366 T* m_array;
367};
368
369//------------------------------------------------------------------------
370template <class T>
371void pod_vector<T>::capacity(unsigned cap, unsigned extra_tail) {
372 m_size = 0;
373 if (cap > m_capacity) {
374 pod_allocator<T>::deallocate(m_array, m_capacity);
375 m_capacity = cap + extra_tail;
376 m_array = m_capacity ? pod_allocator<T>::allocate(m_capacity) : 0;
377 }
378}
379
380//------------------------------------------------------------------------
381template <class T>
382void pod_vector<T>::allocate(unsigned size, unsigned extra_tail) {
383 capacity(size, extra_tail);
384 m_size = size;
385}
386
387//------------------------------------------------------------------------
388template <class T>
389void pod_vector<T>::resize(unsigned new_size) {
390 if (new_size > m_size) {
391 if (new_size > m_capacity) {
392 T* data = pod_allocator<T>::allocate(new_size);
393 memcpy(data, m_array, m_size * sizeof(T));
394 pod_allocator<T>::deallocate(m_array, m_capacity);
395 m_array = data;
396 }
397 } else {
398 m_size = new_size;
399 }
400}
401
402//------------------------------------------------------------------------
403template <class T>
404pod_vector<T>::pod_vector(unsigned cap, unsigned extra_tail)
405 : m_size(0),
406 m_capacity(cap + extra_tail),
407 m_array(pod_allocator<T>::allocate(m_capacity)) {}
408
409//------------------------------------------------------------------------
410template <class T>
411pod_vector<T>::pod_vector(const pod_vector<T>& v)
412 : m_size(v.m_size),
413 m_capacity(v.m_capacity),
414 m_array(v.m_capacity ? pod_allocator<T>::allocate(v.m_capacity) : 0) {
415 memcpy(m_array, v.m_array, sizeof(T) * v.m_size);
416}
417
418//------------------------------------------------------------------------
419template <class T>
420const pod_vector<T>& pod_vector<T>::operator=(const pod_vector<T>& v) {
421 allocate(v.m_size);
422 if (v.m_size) memcpy(m_array, v.m_array, sizeof(T) * v.m_size);
423 return *this;
424}
425
426//------------------------------------------------------------------------
427template <class T>
428void pod_vector<T>::serialize(int8u* ptr) const {
429 if (m_size) memcpy(ptr, m_array, m_size * sizeof(T));
430}
431
432//------------------------------------------------------------------------
433template <class T>
434void pod_vector<T>::deserialize(const int8u* data, unsigned byte_size) {
435 byte_size /= sizeof(T);
436 allocate(byte_size);
437 if (byte_size) memcpy(m_array, data, byte_size * sizeof(T));
438}
439
440//------------------------------------------------------------------------
441template <class T>
442void pod_vector<T>::insert_at(unsigned pos, const T& val) {
443 if (pos >= m_size) {
444 m_array[m_size] = val;
445 } else {
446 memmove(m_array + pos + 1, m_array + pos, (m_size - pos) * sizeof(T));
447 m_array[pos] = val;
448 }
449 ++m_size;
450}
451
452//---------------------------------------------------------------pod_bvector
453// A simple class template to store Plain Old Data, similar to std::deque
454// It doesn't reallocate memory but instead, uses blocks of data of size
455// of (1 << S), that is, power of two. The data is NOT contiguous in memory,
456// so the only valid access method is operator [] or curr(), prev(), next()
457//
458// There reallocs occure only when the pool of pointers to blocks needs
459// to be extended (it happens very rarely). You can control the value
460// of increment to reallocate the pointer buffer. See the second constructor.
461// By default, the incremeent value equals (1 << S), i.e., the block size.
462//------------------------------------------------------------------------
463template <class T, unsigned S = 6>
465 public:
466 enum block_scale_e {
467 block_shift = S,
468 block_size = 1 << block_shift,
469 block_mask = block_size - 1
470 };
471
472 typedef T value_type;
473
474 ~pod_bvector();
475
476 pod_bvector();
477
478 pod_bvector(unsigned block_ptr_inc);
479
480 // Copying
482
483 const pod_bvector<T, S>& operator=(const pod_bvector<T, S>& v);
484
485 void remove_all() {
486 m_size = 0;
487 }
488
489 void clear() {
490 m_size = 0;
491 }
492
493 void free_all() {
494 free_tail(0);
495 }
496
497 void free_tail(unsigned size);
498
499 void add(const T& val);
500
501 void push_back(const T& val) {
502 add(val);
503 }
504
505 void modify_last(const T& val);
506
507 void remove_last();
508
509 int allocate_continuous_block(unsigned num_elements);
510
511 void add_array(const T* ptr, unsigned num_elem) {
512 while (num_elem--) {
513 add(*ptr++);
514 }
515 }
516
517 template <class DataAccessor>
518 void add_data(DataAccessor& data) {
519 while (data.size()) {
520 add(*data);
521 ++data;
522 }
523 }
524
525 void cut_at(unsigned size) {
526 if (size < m_size) m_size = size;
527 }
528
529 unsigned size() const {
530 return m_size;
531 }
532
533 const T& operator[](unsigned i) const {
534 return m_blocks[i >> block_shift][i & block_mask];
535 }
536
537 T& operator[](unsigned i) {
538 return m_blocks[i >> block_shift][i & block_mask];
539 }
540
541 const T& at(unsigned i) const {
542 return m_blocks[i >> block_shift][i & block_mask];
543 }
544
545 T& at(unsigned i) {
546 return m_blocks[i >> block_shift][i & block_mask];
547 }
548
549 T value_at(unsigned i) const {
550 return m_blocks[i >> block_shift][i & block_mask];
551 }
552
553 const T& curr(unsigned idx) const {
554 return (*this)[idx];
555 }
556
557 T& curr(unsigned idx) {
558 return (*this)[idx];
559 }
560
561 const T& prev(unsigned idx) const {
562 return (*this)[(idx + m_size - 1) % m_size];
563 }
564
565 T& prev(unsigned idx) {
566 return (*this)[(idx + m_size - 1) % m_size];
567 }
568
569 const T& next(unsigned idx) const {
570 return (*this)[(idx + 1) % m_size];
571 }
572
573 T& next(unsigned idx) {
574 return (*this)[(idx + 1) % m_size];
575 }
576
577 const T& last() const {
578 return (*this)[m_size - 1];
579 }
580
581 T& last() {
582 return (*this)[m_size - 1];
583 }
584
585 unsigned byte_size() const;
586
587 void serialize(int8u* ptr) const;
588
589 void deserialize(const int8u* data, unsigned byte_size);
590
591 void deserialize(unsigned start, const T& empty_val, const int8u* data, unsigned byte_size);
592
593 template <class ByteAccessor>
594 void deserialize(ByteAccessor data) {
595 remove_all();
596 unsigned elem_size = data.size() / sizeof(T);
597
598 for (unsigned i = 0; i < elem_size; ++i) {
599 int8u* ptr = (int8u*)data_ptr();
600 for (unsigned j = 0; j < sizeof(T); ++j) {
601 *ptr++ = *data;
602 ++data;
603 }
604 ++m_size;
605 }
606 }
607
608 template <class ByteAccessor>
609 void deserialize(unsigned start, const T& empty_val, ByteAccessor data) {
610 while (m_size < start) {
611 add(empty_val);
612 }
613
614 unsigned elem_size = data.size() / sizeof(T);
615 for (unsigned i = 0; i < elem_size; ++i) {
616 int8u* ptr;
617 if (start + i < m_size) {
618 ptr = (int8u*)(&((*this)[start + i]));
619 } else {
620 ptr = (int8u*)data_ptr();
621 ++m_size;
622 }
623 for (unsigned j = 0; j < sizeof(T); ++j) {
624 *ptr++ = *data;
625 ++data;
626 }
627 }
628 }
629
630 const T* block(unsigned nb) const {
631 return m_blocks[nb];
632 }
633
634 private:
635 void allocate_block(unsigned nb);
636
637 T* data_ptr();
638
639 unsigned m_size;
640 unsigned m_num_blocks;
641 unsigned m_max_blocks;
642 T** m_blocks;
643 unsigned m_block_ptr_inc;
644};
645
646//------------------------------------------------------------------------
647template <class T, unsigned S>
649 if (m_num_blocks) {
650 T** blk = m_blocks + m_num_blocks - 1;
651 while (m_num_blocks--) {
652 pod_allocator<T>::deallocate(*blk, block_size);
653 --blk;
654 }
655 }
656 pod_allocator<T*>::deallocate(m_blocks, m_max_blocks);
657}
658
659//------------------------------------------------------------------------
660template <class T, unsigned S>
661void pod_bvector<T, S>::free_tail(unsigned size) {
662 if (size < m_size) {
663 unsigned nb = (size + block_mask) >> block_shift;
664 while (m_num_blocks > nb) {
665 pod_allocator<T>::deallocate(m_blocks[--m_num_blocks], block_size);
666 }
667 if (m_num_blocks == 0) {
668 pod_allocator<T*>::deallocate(m_blocks, m_max_blocks);
669 m_blocks = 0;
670 m_max_blocks = 0;
671 }
672 m_size = size;
673 }
674}
675
676//------------------------------------------------------------------------
677template <class T, unsigned S>
678pod_bvector<T, S>::pod_bvector()
679 : m_size(0),
680 m_num_blocks(0),
681 m_max_blocks(0),
682 m_blocks(0),
683 m_block_ptr_inc(block_size) {}
684
685//------------------------------------------------------------------------
686template <class T, unsigned S>
687pod_bvector<T, S>::pod_bvector(unsigned block_ptr_inc)
688 : m_size(0),
689 m_num_blocks(0),
690 m_max_blocks(0),
691 m_blocks(0),
692 m_block_ptr_inc(block_ptr_inc) {}
693
694//------------------------------------------------------------------------
695template <class T, unsigned S>
696pod_bvector<T, S>::pod_bvector(const pod_bvector<T, S>& v)
697 : m_size(v.m_size),
698 m_num_blocks(v.m_num_blocks),
699 m_max_blocks(v.m_max_blocks),
700 m_blocks(v.m_max_blocks ? pod_allocator<T*>::allocate(v.m_max_blocks) : 0),
701 m_block_ptr_inc(v.m_block_ptr_inc) {
702 unsigned i;
703 for (i = 0; i < v.m_num_blocks; ++i) {
704 m_blocks[i] = pod_allocator<T>::allocate(block_size);
705 memcpy(m_blocks[i], v.m_blocks[i], block_size * sizeof(T));
706 }
707}
708
709//------------------------------------------------------------------------
710template <class T, unsigned S>
711const pod_bvector<T, S>& pod_bvector<T, S>::operator=(const pod_bvector<T, S>& v) {
712 unsigned i;
713 for (i = m_num_blocks; i < v.m_num_blocks; ++i) {
714 allocate_block(i);
715 }
716 for (i = 0; i < v.m_num_blocks; ++i) {
717 memcpy(m_blocks[i], v.m_blocks[i], block_size * sizeof(T));
718 }
719 m_size = v.m_size;
720 return *this;
721}
722
723//------------------------------------------------------------------------
724template <class T, unsigned S>
725void pod_bvector<T, S>::allocate_block(unsigned nb) {
726 if (nb >= m_max_blocks) {
727 T** new_blocks = pod_allocator<T*>::allocate(m_max_blocks + m_block_ptr_inc);
728
729 if (m_blocks) {
730 memcpy(new_blocks, m_blocks, m_num_blocks * sizeof(T*));
731
732 pod_allocator<T*>::deallocate(m_blocks, m_max_blocks);
733 }
734 m_blocks = new_blocks;
735 m_max_blocks += m_block_ptr_inc;
736 }
737 m_blocks[nb] = pod_allocator<T>::allocate(block_size);
738 m_num_blocks++;
739}
740
741//------------------------------------------------------------------------
742template <class T, unsigned S>
743inline T* pod_bvector<T, S>::data_ptr() {
744 unsigned nb = m_size >> block_shift;
745 if (nb >= m_num_blocks) {
746 allocate_block(nb);
747 }
748 return m_blocks[nb] + (m_size & block_mask);
749}
750
751//------------------------------------------------------------------------
752template <class T, unsigned S>
753inline void pod_bvector<T, S>::add(const T& val) {
754 *data_ptr() = val;
755 ++m_size;
756}
757
758//------------------------------------------------------------------------
759template <class T, unsigned S>
760inline void pod_bvector<T, S>::remove_last() {
761 if (m_size) --m_size;
762}
763
764//------------------------------------------------------------------------
765template <class T, unsigned S>
766void pod_bvector<T, S>::modify_last(const T& val) {
767 remove_last();
768 add(val);
769}
770
771//------------------------------------------------------------------------
772template <class T, unsigned S>
773int pod_bvector<T, S>::allocate_continuous_block(unsigned num_elements) {
774 if (num_elements < block_size) {
775 data_ptr(); // Allocate initial block if necessary
776 unsigned rest = block_size - (m_size & block_mask);
777 unsigned index;
778 if (num_elements <= rest) {
779 // The rest of the block is good, we can use it
780 //-----------------
781 index = m_size;
782 m_size += num_elements;
783 return index;
784 }
785
786 // New block
787 //---------------
788 m_size += rest;
789 data_ptr();
790 index = m_size;
791 m_size += num_elements;
792 return index;
793 }
794 return -1; // Impossible to allocate
795}
796
797//------------------------------------------------------------------------
798template <class T, unsigned S>
799unsigned pod_bvector<T, S>::byte_size() const {
800 return m_size * sizeof(T);
801}
802
803//------------------------------------------------------------------------
804template <class T, unsigned S>
805void pod_bvector<T, S>::serialize(int8u* ptr) const {
806 unsigned i;
807 for (i = 0; i < m_size; i++) {
808 memcpy(ptr, &(*this)[i], sizeof(T));
809 ptr += sizeof(T);
810 }
811}
812
813//------------------------------------------------------------------------
814template <class T, unsigned S>
815void pod_bvector<T, S>::deserialize(const int8u* data, unsigned byte_size) {
816 remove_all();
817 byte_size /= sizeof(T);
818 for (unsigned i = 0; i < byte_size; ++i) {
819 T* ptr = data_ptr();
820 memcpy(ptr, data, sizeof(T));
821 ++m_size;
822 data += sizeof(T);
823 }
824}
825
826// Replace or add a number of elements starting from "start" position
827//------------------------------------------------------------------------
828template <class T, unsigned S>
829void pod_bvector<T, S>::deserialize(unsigned start, const T& empty_val, const int8u* data, unsigned byte_size) {
830 while (m_size < start) {
831 add(empty_val);
832 }
833
834 byte_size /= sizeof(T);
835 for (unsigned i = 0; i < byte_size; ++i) {
836 if (start + i < m_size) {
837 memcpy(&((*this)[start + i]), data, sizeof(T));
838 } else {
839 T* ptr = data_ptr();
840 memcpy(ptr, data, sizeof(T));
841 ++m_size;
842 }
843 data += sizeof(T);
844 }
845}
846
847//---------------------------------------------------------block_allocator
848// Allocator for arbitrary POD data. Most usable in different cache
849// systems for efficient memory allocations.
850// Memory is allocated with blocks of fixed size ("block_size" in
851// the constructor). If required size exceeds the block size the allocator
852// creates a new block of the required size. However, the most efficient
853// use is when the average reqired size is much less than the block size.
854//------------------------------------------------------------------------
856 struct block_type {
857 int8u* data;
858 unsigned size;
859 };
860
861 public:
862 void remove_all() {
863 if (m_num_blocks) {
864 block_type* blk = m_blocks + m_num_blocks - 1;
865 while (m_num_blocks--) {
867 --blk;
868 }
869 pod_allocator<block_type>::deallocate(m_blocks, m_max_blocks);
870 }
871 m_num_blocks = 0;
872 m_max_blocks = 0;
873 m_blocks = 0;
874 m_buf_ptr = 0;
875 m_rest = 0;
876 }
877
879 remove_all();
880 }
881
882 block_allocator(unsigned block_size, unsigned block_ptr_inc = 256 - 8)
883 : m_block_size(block_size),
884 m_block_ptr_inc(block_ptr_inc),
885 m_num_blocks(0),
886 m_max_blocks(0),
887 m_blocks(0),
888 m_buf_ptr(0),
889 m_rest(0) {}
890
891 int8u* allocate(unsigned size, unsigned alignment = 1) {
892 if (size == 0) return 0;
893 if (size <= m_rest) {
894 int8u* ptr = m_buf_ptr;
895 if (alignment > 1) {
896 unsigned align = (alignment - unsigned((size_t)ptr) % alignment) % alignment;
897
898 size += align;
899 ptr += align;
900 if (size <= m_rest) {
901 m_rest -= size;
902 m_buf_ptr += size;
903 return ptr;
904 }
905 allocate_block(size);
906 return allocate(size - align, alignment);
907 }
908 m_rest -= size;
909 m_buf_ptr += size;
910 return ptr;
911 }
912 allocate_block(size + alignment - 1);
913 return allocate(size, alignment);
914 }
915
916 private:
917 void allocate_block(unsigned size) {
918 if (size < m_block_size) size = m_block_size;
919 if (m_num_blocks >= m_max_blocks) {
920 block_type* new_blocks = pod_allocator<block_type>::allocate(m_max_blocks + m_block_ptr_inc);
921
922 if (m_blocks) {
923 memcpy(new_blocks, m_blocks, m_num_blocks * sizeof(block_type));
924 pod_allocator<block_type>::deallocate(m_blocks, m_max_blocks);
925 }
926 m_blocks = new_blocks;
927 m_max_blocks += m_block_ptr_inc;
928 }
929
930 m_blocks[m_num_blocks].size = size;
931 m_blocks[m_num_blocks].data = m_buf_ptr = pod_allocator<int8u>::allocate(size);
932
933 m_num_blocks++;
934 m_rest = size;
935 }
936
937 unsigned m_block_size;
938 unsigned m_block_ptr_inc;
939 unsigned m_num_blocks;
940 unsigned m_max_blocks;
941 block_type* m_blocks;
942 int8u* m_buf_ptr;
943 unsigned m_rest;
944};
945
946//------------------------------------------------------------------------
947enum quick_sort_threshold_e {
948 quick_sort_threshold = 9
949};
950
951//-----------------------------------------------------------swap_elements
952template <class T>
953inline void swap_elements(T& a, T& b) {
954 T temp = a;
955 a = b;
956 b = temp;
957}
958
959//--------------------------------------------------------------quick_sort
960template <class Array, class Less>
961void quick_sort(Array& arr, Less less) {
962 if (arr.size() < 2) return;
963
964 typename Array::value_type* e1;
965 typename Array::value_type* e2;
966
967 int stack[80];
968 int* top = stack;
969 int limit = arr.size();
970 int base = 0;
971
972 for (;;) {
973 int len = limit - base;
974
975 int i;
976 int j;
977 int pivot;
978
979 if (len > quick_sort_threshold) {
980 // we use base + len/2 as the pivot
981 pivot = base + len / 2;
982 swap_elements(arr[base], arr[pivot]);
983
984 i = base + 1;
985 j = limit - 1;
986
987 // now ensure that *i <= *base <= *j
988 e1 = &(arr[j]);
989 e2 = &(arr[i]);
990 if (less(*e1, *e2)) swap_elements(*e1, *e2);
991
992 e1 = &(arr[base]);
993 e2 = &(arr[i]);
994 if (less(*e1, *e2)) swap_elements(*e1, *e2);
995
996 e1 = &(arr[j]);
997 e2 = &(arr[base]);
998 if (less(*e1, *e2)) swap_elements(*e1, *e2);
999
1000 for (;;) {
1001 do i++;
1002 while (less(arr[i], arr[base]));
1003 do j--;
1004 while (less(arr[base], arr[j]));
1005
1006 if (i > j) {
1007 break;
1008 }
1009
1010 swap_elements(arr[i], arr[j]);
1011 }
1012
1013 swap_elements(arr[base], arr[j]);
1014
1015 // now, push the largest sub-array
1016 if (j - base > limit - i) {
1017 top[0] = base;
1018 top[1] = j;
1019 base = i;
1020 } else {
1021 top[0] = i;
1022 top[1] = limit;
1023 limit = j;
1024 }
1025 top += 2;
1026 } else {
1027 // the sub-array is small, perform insertion sort
1028 j = base;
1029 i = j + 1;
1030
1031 for (; i < limit; j = i, i++) {
1032 for (; less(*(e1 = &(arr[j + 1])), *(e2 = &(arr[j]))); j--) {
1033 swap_elements(*e1, *e2);
1034 if (j == base) {
1035 break;
1036 }
1037 }
1038 }
1039 if (top > stack) {
1040 top -= 2;
1041 base = top[0];
1042 limit = top[1];
1043 } else {
1044 break;
1045 }
1046 }
1047 }
1048}
1049
1050//------------------------------------------------------remove_duplicates
1051// Remove duplicates from a sorted array. It doesn't cut the
1052// tail of the array, it just returns the number of remaining elements.
1053//-----------------------------------------------------------------------
1054template <class Array, class Equal>
1055unsigned remove_duplicates(Array& arr, Equal equal) {
1056 if (arr.size() < 2) return arr.size();
1057
1058 unsigned i, j;
1059 for (i = 1, j = 1; i < arr.size(); i++) {
1060 typename Array::value_type& e = arr[i];
1061 if (!equal(e, arr[i - 1])) {
1062 arr[j++] = e;
1063 }
1064 }
1065 return j;
1066}
1067
1068//--------------------------------------------------------invert_container
1069template <class Array>
1070void invert_container(Array& arr) {
1071 int i = 0;
1072 int j = arr.size() - 1;
1073 while (i < j) {
1074 swap_elements(arr[i++], arr[j--]);
1075 }
1076}
1077
1078//------------------------------------------------------binary_search_pos
1079template <class Array, class Value, class Less>
1080unsigned binary_search_pos(const Array& arr, const Value& val, Less less) {
1081 if (arr.size() == 0) return 0;
1082
1083 unsigned beg = 0;
1084 unsigned end = arr.size() - 1;
1085
1086 if (less(val, arr[0])) return 0;
1087 if (less(arr[end], val)) return end + 1;
1088
1089 while (end - beg > 1) {
1090 unsigned mid = (end + beg) >> 1;
1091 if (less(val, arr[mid]))
1092 end = mid;
1093 else
1094 beg = mid;
1095 }
1096
1097 // if(beg <= 0 && less(val, arr[0])) return 0;
1098 // if(end >= arr.size() - 1 && less(arr[end], val)) ++end;
1099
1100 return end;
1101}
1102
1103//----------------------------------------------------------range_adaptor
1104template <class Array>
1106 public:
1107 typedef typename Array::value_type value_type;
1108
1109 range_adaptor(Array& array, unsigned start, unsigned size)
1110 : m_array(array),
1111 m_start(start),
1112 m_size(size) {}
1113
1114 unsigned size() const {
1115 return m_size;
1116 }
1117
1118 const value_type& operator[](unsigned i) const {
1119 return m_array[m_start + i];
1120 }
1121
1122 value_type& operator[](unsigned i) {
1123 return m_array[m_start + i];
1124 }
1125
1126 const value_type& at(unsigned i) const {
1127 return m_array[m_start + i];
1128 }
1129
1130 value_type& at(unsigned i) {
1131 return m_array[m_start + i];
1132 }
1133
1134 value_type value_at(unsigned i) const {
1135 return m_array[m_start + i];
1136 }
1137
1138 private:
1139 Array& m_array;
1140 unsigned m_start;
1141 unsigned m_size;
1142};
1143
1144//---------------------------------------------------------------int_less
1145inline bool int_less(int a, int b) {
1146 return a < b;
1147}
1148
1149//------------------------------------------------------------int_greater
1150inline bool int_greater(int a, int b) {
1151 return a > b;
1152}
1153
1154//----------------------------------------------------------unsigned_less
1155inline bool unsigned_less(unsigned a, unsigned b) {
1156 return a < b;
1157}
1158
1159//-------------------------------------------------------unsigned_greater
1160inline bool unsigned_greater(unsigned a, unsigned b) {
1161 return a > b;
1162}
1163} // namespace agg
1164
1165#endif
Definition agg_array.h:855
Definition agg_array.h:37
Definition agg_array.h:181
Definition agg_array.h:76
Definition agg_array.h:122
Definition agg_array.h:464
Definition agg_array.h:259
Definition agg_array.h:1105
Definition agg_basics.h:45