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