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