Home | History | Annotate | Download | only in agg23
      1 
      2 //----------------------------------------------------------------------------
      3 // Anti-Grain Geometry - Version 2.3
      4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
      5 //
      6 // Permission to copy, use, modify, sell and distribute this software
      7 // is granted provided this copyright notice appears in all copies.
      8 // This software is provided "as is" without express or implied
      9 // warranty, and with no claim as to its suitability for any purpose.
     10 //
     11 //----------------------------------------------------------------------------
     12 // Contact: mcseem (at) antigrain.com
     13 //          mcseemagg (at) yahoo.com
     14 //          http://www.antigrain.com
     15 //----------------------------------------------------------------------------
     16 #ifndef AGG_ARRAY_INCLUDED
     17 #define AGG_ARRAY_INCLUDED
     18 
     19 #include "agg_basics.h"
     20 #include "core/include/fxcrt/fx_memory.h"  // For FXSYS_* macros.
     21 
     22 namespace agg
     23 {
     24 template <class T>
     25 class pod_array {
     26 public:
     27     typedef T value_type;
     28     ~pod_array()
     29     {
     30         FX_Free(m_array);
     31     }
     32     pod_array() : m_size(0), m_capacity(0), m_array(0) {}
     33     pod_array(unsigned cap, unsigned extra_tail = 0);
     34     pod_array(const pod_array<T>&);
     35     const pod_array<T>& operator = (const pod_array<T>&);
     36     void capacity(unsigned cap, unsigned extra_tail = 0);
     37     unsigned capacity() const
     38     {
     39         return m_capacity;
     40     }
     41     void allocate(unsigned size, unsigned extra_tail = 0);
     42     void resize(unsigned new_size);
     43     void zero()
     44     {
     45         FXSYS_memset(m_array, 0, sizeof(T) * m_size);
     46     }
     47     void add(const T& v)
     48     {
     49         m_array[m_size++] = v;
     50     }
     51     void inc_size(unsigned size)
     52     {
     53         m_size += size;
     54     }
     55     unsigned size()      const
     56     {
     57         return m_size;
     58     }
     59     unsigned byte_size() const
     60     {
     61         return m_size * sizeof(T);
     62     }
     63     const T& operator [] (unsigned i) const
     64     {
     65         return m_array[i];
     66     }
     67     T& operator [] (unsigned i)
     68     {
     69         return m_array[i];
     70     }
     71     const T& at(unsigned i) const
     72     {
     73         return m_array[i];
     74     }
     75     T& at(unsigned i)
     76     {
     77         return m_array[i];
     78     }
     79     T  value_at(unsigned i) const
     80     {
     81         return m_array[i];
     82     }
     83     const T* data() const
     84     {
     85         return m_array;
     86     }
     87     T* data()
     88     {
     89         return m_array;
     90     }
     91     void remove_all()
     92     {
     93         m_size = 0;
     94     }
     95     void cut_at(unsigned num)
     96     {
     97         if(num < m_size) {
     98             m_size = num;
     99         }
    100     }
    101 private:
    102     unsigned m_size;
    103     unsigned m_capacity;
    104     T*       m_array;
    105 };
    106 template<class T>
    107 void pod_array<T>::capacity(unsigned cap, unsigned extra_tail)
    108 {
    109     m_size = 0;
    110     unsigned full_cap = cap + extra_tail;
    111     if(full_cap < cap) {
    112         FX_Free(m_array);
    113         m_array = 0;
    114         m_capacity = 0;
    115     } else if(full_cap > m_capacity) {
    116         FX_Free(m_array);
    117         m_array = FX_Alloc(T, full_cap);
    118         m_capacity = full_cap;
    119     }
    120 }
    121 template<class T>
    122 void pod_array<T>::allocate(unsigned size, unsigned extra_tail)
    123 {
    124     capacity(size, extra_tail);
    125     m_size = size;
    126 }
    127 template<class T>
    128 void pod_array<T>::resize(unsigned new_size)
    129 {
    130     if(new_size > m_size) {
    131         if(new_size > m_capacity) {
    132             T* data = FX_Alloc(T, new_size);
    133             FXSYS_memcpy(data, m_array, m_size * sizeof(T));
    134             FX_Free(m_array);
    135             m_array = data;
    136         }
    137     } else {
    138         m_size = new_size;
    139     }
    140 }
    141 template<class T> pod_array<T>::pod_array(unsigned cap, unsigned extra_tail) :
    142     m_size(0), m_capacity(cap + extra_tail), m_array(FX_Alloc(T, m_capacity)) {}
    143 template<class T> pod_array<T>::pod_array(const pod_array<T>& v) :
    144     m_size(v.m_size),
    145     m_capacity(v.m_capacity),
    146     m_array(v.m_capacity ? FX_Alloc(T, v.m_capacity) : 0)
    147 {
    148     FXSYS_memcpy(m_array, v.m_array, sizeof(T) * v.m_size);
    149 }
    150 template<class T> const pod_array<T>&
    151 pod_array<T>::operator = (const pod_array<T>&v)
    152 {
    153     allocate(v.m_size);
    154     if(v.m_size) {
    155         FXSYS_memcpy(m_array, v.m_array, sizeof(T) * v.m_size);
    156     }
    157     return *this;
    158 }
    159 template<class T, unsigned S = 6> class pod_deque
    160 {
    161 public:
    162     enum block_scale_e {
    163         block_shift = S,
    164         block_size  = 1 << block_shift,
    165         block_mask  = block_size - 1
    166     };
    167     typedef T value_type;
    168     ~pod_deque();
    169     pod_deque();
    170     pod_deque(unsigned block_ptr_inc);
    171     pod_deque(const pod_deque<T, S>& v);
    172     const pod_deque<T, S>& operator = (const pod_deque<T, S>& v);
    173     void remove_all()
    174     {
    175         m_size = 0;
    176     }
    177     void free_all()
    178     {
    179         free_tail(0);
    180     }
    181     void free_tail(unsigned size);
    182     void add(const T& val);
    183     void modify_last(const T& val);
    184     void remove_last();
    185     int allocate_continuous_block(unsigned num_elements);
    186     void add_array(const T* ptr, unsigned num_elem)
    187     {
    188         while(num_elem--) {
    189             add(*ptr++);
    190         }
    191     }
    192     template<class DataAccessor> void add_data(DataAccessor& data)
    193     {
    194         while(data.size()) {
    195             add(*data);
    196             ++data;
    197         }
    198     }
    199     void cut_at(unsigned size)
    200     {
    201         if(size < m_size) {
    202             m_size = size;
    203         }
    204     }
    205     unsigned size() const
    206     {
    207         return m_size;
    208     }
    209     const T& operator [] (unsigned i) const
    210     {
    211         return m_blocks[i >> block_shift][i & block_mask];
    212     }
    213     T& operator [] (unsigned i)
    214     {
    215         return m_blocks[i >> block_shift][i & block_mask];
    216     }
    217     const T& at(unsigned i) const
    218     {
    219         return m_blocks[i >> block_shift][i & block_mask];
    220     }
    221     T& at(unsigned i)
    222     {
    223         return m_blocks[i >> block_shift][i & block_mask];
    224     }
    225     T value_at(unsigned i) const
    226     {
    227         return m_blocks[i >> block_shift][i & block_mask];
    228     }
    229     const T& curr(unsigned idx) const
    230     {
    231         return (*this)[idx];
    232     }
    233     T& curr(unsigned idx)
    234     {
    235         return (*this)[idx];
    236     }
    237     const T& prev(unsigned idx) const
    238     {
    239         return (*this)[(idx + m_size - 1) % m_size];
    240     }
    241     T& prev(unsigned idx)
    242     {
    243         return (*this)[(idx + m_size - 1) % m_size];
    244     }
    245     const T& next(unsigned idx) const
    246     {
    247         return (*this)[(idx + 1) % m_size];
    248     }
    249     T& next(unsigned idx)
    250     {
    251         return (*this)[(idx + 1) % m_size];
    252     }
    253     const T& last() const
    254     {
    255         return (*this)[m_size - 1];
    256     }
    257     T& last()
    258     {
    259         return (*this)[m_size - 1];
    260     }
    261     unsigned byte_size() const;
    262     const T* block(unsigned nb) const
    263     {
    264         return m_blocks[nb];
    265     }
    266 public:
    267     void allocate_block(unsigned nb);
    268     T*   data_ptr();
    269     unsigned        m_size;
    270     unsigned        m_num_blocks;
    271     unsigned        m_max_blocks;
    272     T**             m_blocks;
    273     unsigned        m_block_ptr_inc;
    274 };
    275 template<class T, unsigned S> pod_deque<T, S>::~pod_deque()
    276 {
    277     if(m_num_blocks) {
    278         T** blk = m_blocks + m_num_blocks - 1;
    279         while(m_num_blocks--) {
    280             FX_Free(*blk);
    281             --blk;
    282         }
    283         FX_Free(m_blocks);
    284     }
    285 }
    286 template<class T, unsigned S>
    287 void pod_deque<T, S>::free_tail(unsigned size)
    288 {
    289     if(size < m_size) {
    290         unsigned nb = (size + block_mask) >> block_shift;
    291         while(m_num_blocks > nb) {
    292             FX_Free(m_blocks[--m_num_blocks]);
    293         }
    294         m_size = size;
    295     }
    296 }
    297 template<class T, unsigned S> pod_deque<T, S>::pod_deque() :
    298     m_size(0),
    299     m_num_blocks(0),
    300     m_max_blocks(0),
    301     m_blocks(0),
    302     m_block_ptr_inc(block_size)
    303 {
    304 }
    305 template<class T, unsigned S>
    306 pod_deque<T, S>::pod_deque(unsigned block_ptr_inc) :
    307     m_size(0),
    308     m_num_blocks(0),
    309     m_max_blocks(0),
    310     m_blocks(0),
    311     m_block_ptr_inc(block_ptr_inc)
    312 {
    313 }
    314 template<class T, unsigned S>
    315 pod_deque<T, S>::pod_deque(const pod_deque<T, S>& v) :
    316     m_size(v.m_size),
    317     m_num_blocks(v.m_num_blocks),
    318     m_max_blocks(v.m_max_blocks),
    319     m_blocks(v.m_max_blocks ? FX_Alloc(T*, v.m_max_blocks) : 0),
    320     m_block_ptr_inc(v.m_block_ptr_inc)
    321 {
    322     unsigned i;
    323     for(i = 0; i < v.m_num_blocks; ++i) {
    324         m_blocks[i] = FX_Alloc(T, block_size);
    325         FXSYS_memcpy(m_blocks[i], v.m_blocks[i], block_size * sizeof(T));
    326     }
    327 }
    328 template<class T, unsigned S>
    329 const pod_deque<T, S>& pod_deque<T, S>::operator = (const pod_deque<T, S>& v)
    330 {
    331     unsigned i;
    332     for(i = m_num_blocks; i < v.m_num_blocks; ++i) {
    333         allocate_block(i);
    334     }
    335     for(i = 0; i < v.m_num_blocks; ++i) {
    336         FXSYS_memcpy(m_blocks[i], v.m_blocks[i], block_size * sizeof(T));
    337     }
    338     m_size = v.m_size;
    339     return *this;
    340 }
    341 template<class T, unsigned S>
    342 void pod_deque<T, S>::allocate_block(unsigned nb)
    343 {
    344     if(nb >= m_max_blocks) {
    345         T** new_blocks = FX_Alloc(T*, m_max_blocks + m_block_ptr_inc);
    346         if(m_blocks) {
    347             FXSYS_memcpy(new_blocks,
    348                          m_blocks,
    349                          m_num_blocks * sizeof(T*));
    350             FX_Free(m_blocks);
    351         }
    352         m_blocks = new_blocks;
    353         m_max_blocks += m_block_ptr_inc;
    354     }
    355     m_blocks[nb] = FX_Alloc(T, block_size);
    356     m_num_blocks++;
    357 }
    358 template<class T, unsigned S>
    359 inline T* pod_deque<T, S>::data_ptr()
    360 {
    361     unsigned nb = m_size >> block_shift;
    362     if(nb >= m_num_blocks) {
    363         allocate_block(nb);
    364     }
    365     return m_blocks[nb] + (m_size & block_mask);
    366 }
    367 template<class T, unsigned S>
    368 inline void pod_deque<T, S>::add(const T& val)
    369 {
    370     *data_ptr() = val;
    371     ++m_size;
    372 }
    373 template<class T, unsigned S>
    374 inline void pod_deque<T, S>::remove_last()
    375 {
    376     if(m_size) {
    377         --m_size;
    378     }
    379 }
    380 template<class T, unsigned S>
    381 void pod_deque<T, S>::modify_last(const T& val)
    382 {
    383     remove_last();
    384     add(val);
    385 }
    386 template<class T, unsigned S>
    387 int pod_deque<T, S>::allocate_continuous_block(unsigned num_elements)
    388 {
    389     if(num_elements < block_size) {
    390         data_ptr();
    391         unsigned rest = block_size - (m_size & block_mask);
    392         unsigned index;
    393         if(num_elements <= rest) {
    394             index = m_size;
    395             m_size += num_elements;
    396             return index;
    397         }
    398         m_size += rest;
    399         data_ptr();
    400         index = m_size;
    401         m_size += num_elements;
    402         return index;
    403     }
    404     return -1;
    405 }
    406 template<class T, unsigned S>
    407 unsigned pod_deque<T, S>::byte_size() const
    408 {
    409     return m_size * sizeof(T);
    410 }
    411 class pod_allocator
    412 {
    413 public:
    414     void remove_all()
    415     {
    416         if(m_num_blocks) {
    417             int8u** blk = m_blocks + m_num_blocks - 1;
    418             while(m_num_blocks--) {
    419                 FX_Free(*blk);
    420                 --blk;
    421             }
    422             FX_Free(m_blocks);
    423         }
    424         m_num_blocks = 0;
    425         m_max_blocks = 0;
    426         m_blocks = 0;
    427         m_buf_ptr = 0;
    428         m_rest = 0;
    429     }
    430     ~pod_allocator()
    431     {
    432         remove_all();
    433     }
    434     pod_allocator(unsigned block_size, unsigned block_ptr_inc = 256 - 8) :
    435         m_block_size(block_size),
    436         m_block_ptr_inc(block_ptr_inc),
    437         m_num_blocks(0),
    438         m_max_blocks(0),
    439         m_blocks(0),
    440         m_buf_ptr(0),
    441         m_rest(0)
    442     {
    443     }
    444     int8u* allocate(unsigned size, unsigned alignment = 1)
    445     {
    446         if(size == 0) {
    447             return 0;
    448         }
    449         if(size <= m_rest) {
    450             int8u* ptr = m_buf_ptr;
    451             if(alignment > 1) {
    452                 unsigned align = (alignment - unsigned((size_t)ptr) % alignment) % alignment;
    453                 size += align;
    454                 ptr += align;
    455                 if(size <= m_rest) {
    456                     m_rest -= size;
    457                     m_buf_ptr += size;
    458                     return ptr;
    459                 }
    460                 allocate_block(size);
    461                 return allocate(size - align, alignment);
    462             }
    463             m_rest -= size;
    464             m_buf_ptr += size;
    465             return ptr;
    466         }
    467         allocate_block(size + alignment - 1);
    468         return allocate(size, alignment);
    469     }
    470 private:
    471     void allocate_block(unsigned size)
    472     {
    473         if(size < m_block_size) {
    474             size = m_block_size;
    475         }
    476         if(m_num_blocks >= m_max_blocks) {
    477             int8u** new_blocks = FX_Alloc(int8u*, m_max_blocks + m_block_ptr_inc);
    478             if(m_blocks) {
    479                 FXSYS_memcpy(new_blocks,
    480                              m_blocks,
    481                              m_num_blocks * sizeof(int8u*));
    482                 FX_Free(m_blocks);
    483             }
    484             m_blocks = new_blocks;
    485             m_max_blocks += m_block_ptr_inc;
    486         }
    487         m_blocks[m_num_blocks] = m_buf_ptr = FX_Alloc(int8u, size);
    488         m_num_blocks++;
    489         m_rest = size;
    490     }
    491     unsigned m_block_size;
    492     unsigned m_block_ptr_inc;
    493     unsigned m_num_blocks;
    494     unsigned m_max_blocks;
    495     int8u**  m_blocks;
    496     int8u*   m_buf_ptr;
    497     unsigned m_rest;
    498 };
    499 enum quick_sort_threshold_e {
    500     quick_sort_threshold = 9
    501 };
    502 template<class T> inline void swap_elements(T& a, T& b)
    503 {
    504     T temp = a;
    505     a = b;
    506     b = temp;
    507 }
    508 }
    509 #endif
    510