123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119 |
- //----------------------------------------------------------------------------
- // Anti-Grain Geometry - Version 2.4
- // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
- //
- // Permission to copy, use, modify, sell and distribute this software
- // is granted provided this copyright notice appears in all copies.
- // This software is provided "as is" without express or implied
- // warranty, and with no claim as to its suitability for any purpose.
- //
- //----------------------------------------------------------------------------
- // Contact: mcseem@antigrain.com
- // mcseemagg@yahoo.com
- // http://www.antigrain.com
- //----------------------------------------------------------------------------
- #ifndef AGG_ARRAY_INCLUDED
- #define AGG_ARRAY_INCLUDED
- #include <stddef.h>
- #include <string.h>
- #include "agg_basics.h"
- namespace agg
- {
- //-------------------------------------------------------pod_array_adaptor
- template<class T> class pod_array_adaptor
- {
- public:
- typedef T value_type;
- pod_array_adaptor(T* array, unsigned size) :
- m_array(array), m_size(size) {}
- unsigned size() const { return m_size; }
- const T& operator [] (unsigned i) const { return m_array[i]; }
- T& operator [] (unsigned i) { return m_array[i]; }
- const T& at(unsigned i) const { return m_array[i]; }
- T& at(unsigned i) { return m_array[i]; }
- T value_at(unsigned i) const { return m_array[i]; }
- private:
- T* m_array;
- unsigned m_size;
- };
- //---------------------------------------------------------pod_auto_array
- template<class T, unsigned Size> class pod_auto_array
- {
- public:
- typedef T value_type;
- typedef pod_auto_array<T, Size> self_type;
- pod_auto_array() {}
- explicit pod_auto_array(const T* c)
- {
- memcpy(m_array, c, sizeof(T) * Size);
- }
- const self_type& operator = (const T* c)
- {
- memcpy(m_array, c, sizeof(T) * Size);
- return *this;
- }
- static unsigned size() { return Size; }
- const T& operator [] (unsigned i) const { return m_array[i]; }
- T& operator [] (unsigned i) { return m_array[i]; }
- const T& at(unsigned i) const { return m_array[i]; }
- T& at(unsigned i) { return m_array[i]; }
- T value_at(unsigned i) const { return m_array[i]; }
- private:
- T m_array[Size];
- };
- //--------------------------------------------------------pod_auto_vector
- template<class T, unsigned Size> class pod_auto_vector
- {
- public:
- typedef T value_type;
- typedef pod_auto_vector<T, Size> self_type;
- pod_auto_vector() : m_size(0) {}
- void remove_all() { m_size = 0; }
- void clear() { m_size = 0; }
- void add(const T& v) { m_array[m_size++] = v; }
- void push_back(const T& v) { m_array[m_size++] = v; }
- void inc_size(unsigned size) { m_size += size; }
-
- unsigned size() const { return m_size; }
- const T& operator [] (unsigned i) const { return m_array[i]; }
- T& operator [] (unsigned i) { return m_array[i]; }
- const T& at(unsigned i) const { return m_array[i]; }
- T& at(unsigned i) { return m_array[i]; }
- T value_at(unsigned i) const { return m_array[i]; }
- private:
- T m_array[Size];
- unsigned m_size;
- };
- //---------------------------------------------------------------pod_array
- template<class T> class pod_array
- {
- public:
- typedef T value_type;
- typedef pod_array<T> self_type;
- ~pod_array() { pod_allocator<T>::deallocate(m_array, m_size); }
- pod_array() : m_array(0), m_size(0) {}
- pod_array(unsigned size) :
- m_array(pod_allocator<T>::allocate(size)),
- m_size(size)
- {}
- pod_array(const self_type& v) :
- m_array(pod_allocator<T>::allocate(v.m_size)),
- m_size(v.m_size)
- {
- memcpy(m_array, v.m_array, sizeof(T) * m_size);
- }
- void resize(unsigned size)
- {
- if(size != m_size)
- {
- pod_allocator<T>::deallocate(m_array, m_size);
- m_array = pod_allocator<T>::allocate(m_size = size);
- }
- }
- const self_type& operator = (const self_type& v)
- {
- resize(v.size());
- memcpy(m_array, v.m_array, sizeof(T) * m_size);
- return *this;
- }
- unsigned size() const { return m_size; }
- const T& operator [] (unsigned i) const { return m_array[i]; }
- T& operator [] (unsigned i) { return m_array[i]; }
- const T& at(unsigned i) const { return m_array[i]; }
- T& at(unsigned i) { return m_array[i]; }
- T value_at(unsigned i) const { return m_array[i]; }
- const T* data() const { return m_array; }
- T* data() { return m_array; }
- private:
- T* m_array;
- unsigned m_size;
- };
- //--------------------------------------------------------------pod_vector
- // A simple class template to store Plain Old Data, a vector
- // of a fixed size. The data is continous in memory
- //------------------------------------------------------------------------
- template<class T> class pod_vector
- {
- public:
- typedef T value_type;
- ~pod_vector() { pod_allocator<T>::deallocate(m_array, m_capacity); }
- pod_vector() : m_size(0), m_capacity(0), m_array(0) {}
- pod_vector(unsigned cap, unsigned extra_tail=0);
- // Copying
- pod_vector(const pod_vector<T>&);
- const pod_vector<T>& operator = (const pod_vector<T>&);
- // Set new capacity. All data is lost, size is set to zero.
- void capacity(unsigned cap, unsigned extra_tail=0);
- unsigned capacity() const { return m_capacity; }
- // Allocate n elements. All data is lost,
- // but elements can be accessed in range 0...size-1.
- void allocate(unsigned size, unsigned extra_tail=0);
- // Resize keeping the content.
- void resize(unsigned new_size);
- void zero()
- {
- memset(m_array, 0, sizeof(T) * m_size);
- }
- void add(const T& v) { m_array[m_size++] = v; }
- void push_back(const T& v) { m_array[m_size++] = v; }
- void insert_at(unsigned pos, const T& val);
- void inc_size(unsigned size) { m_size += size; }
- unsigned size() const { return m_size; }
- unsigned byte_size() const { return m_size * sizeof(T); }
- void serialize(int8u* ptr) const;
- void deserialize(const int8u* data, unsigned byte_size);
- const T& operator [] (unsigned i) const { return m_array[i]; }
- T& operator [] (unsigned i) { return m_array[i]; }
- const T& at(unsigned i) const { return m_array[i]; }
- T& at(unsigned i) { return m_array[i]; }
- T value_at(unsigned i) const { return m_array[i]; }
- const T* data() const { return m_array; }
- T* data() { return m_array; }
- void remove_all() { m_size = 0; }
- void clear() { m_size = 0; }
- void cut_at(unsigned num) { if(num < m_size) m_size = num; }
- private:
- unsigned m_size;
- unsigned m_capacity;
- T* m_array;
- };
- //------------------------------------------------------------------------
- template<class T>
- void pod_vector<T>::capacity(unsigned cap, unsigned extra_tail)
- {
- m_size = 0;
- if(cap > m_capacity)
- {
- pod_allocator<T>::deallocate(m_array, m_capacity);
- m_capacity = cap + extra_tail;
- m_array = m_capacity ? pod_allocator<T>::allocate(m_capacity) : 0;
- }
- }
- //------------------------------------------------------------------------
- template<class T>
- void pod_vector<T>::allocate(unsigned size, unsigned extra_tail)
- {
- capacity(size, extra_tail);
- m_size = size;
- }
- //------------------------------------------------------------------------
- template<class T>
- void pod_vector<T>::resize(unsigned new_size)
- {
- if(new_size > m_size)
- {
- if(new_size > m_capacity)
- {
- T* data = pod_allocator<T>::allocate(new_size);
- memcpy(data, m_array, m_size * sizeof(T));
- pod_allocator<T>::deallocate(m_array, m_capacity);
- m_array = data;
- }
- }
- else
- {
- m_size = new_size;
- }
- }
- //------------------------------------------------------------------------
- template<class T> pod_vector<T>::pod_vector(unsigned cap, unsigned extra_tail) :
- m_size(0),
- m_capacity(cap + extra_tail),
- m_array(pod_allocator<T>::allocate(m_capacity)) {}
- //------------------------------------------------------------------------
- template<class T> pod_vector<T>::pod_vector(const pod_vector<T>& v) :
- m_size(v.m_size),
- m_capacity(v.m_capacity),
- m_array(v.m_capacity ? pod_allocator<T>::allocate(v.m_capacity) : 0)
- {
- memcpy(m_array, v.m_array, sizeof(T) * v.m_size);
- }
- //------------------------------------------------------------------------
- template<class T> const pod_vector<T>&
- pod_vector<T>::operator = (const pod_vector<T>&v)
- {
- allocate(v.m_size);
- if(v.m_size) memcpy(m_array, v.m_array, sizeof(T) * v.m_size);
- return *this;
- }
- //------------------------------------------------------------------------
- template<class T> void pod_vector<T>::serialize(int8u* ptr) const
- {
- if(m_size) memcpy(ptr, m_array, m_size * sizeof(T));
- }
- //------------------------------------------------------------------------
- template<class T>
- void pod_vector<T>::deserialize(const int8u* data, unsigned byte_size)
- {
- byte_size /= sizeof(T);
- allocate(byte_size);
- if(byte_size) memcpy(m_array, data, byte_size * sizeof(T));
- }
- //------------------------------------------------------------------------
- template<class T>
- void pod_vector<T>::insert_at(unsigned pos, const T& val)
- {
- if(pos >= m_size)
- {
- m_array[m_size] = val;
- }
- else
- {
- memmove(m_array + pos + 1, m_array + pos, (m_size - pos) * sizeof(T));
- m_array[pos] = val;
- }
- ++m_size;
- }
- //---------------------------------------------------------------pod_bvector
- // A simple class template to store Plain Old Data, similar to std::deque
- // It doesn't reallocate memory but instead, uses blocks of data of size
- // of (1 << S), that is, power of two. The data is NOT contiguous in memory,
- // so the only valid access method is operator [] or curr(), prev(), next()
- //
- // There reallocs occure only when the pool of pointers to blocks needs
- // to be extended (it happens very rarely). You can control the value
- // of increment to reallocate the pointer buffer. See the second constructor.
- // By default, the incremeent value equals (1 << S), i.e., the block size.
- //------------------------------------------------------------------------
- template<class T, unsigned S=6> class pod_bvector
- {
- public:
- enum block_scale_e
- {
- block_shift = S,
- block_size = 1 << block_shift,
- block_mask = block_size - 1
- };
- typedef T value_type;
- ~pod_bvector();
- pod_bvector();
- pod_bvector(unsigned block_ptr_inc);
- // Copying
- pod_bvector(const pod_bvector<T, S>& v);
- const pod_bvector<T, S>& operator = (const pod_bvector<T, S>& v);
- void remove_all() { m_size = 0; }
- void clear() { m_size = 0; }
- void free_all() { free_tail(0); }
- void free_tail(unsigned size);
- void add(const T& val);
- void push_back(const T& val) { add(val); }
- void modify_last(const T& val);
- void remove_last();
- int allocate_continuous_block(unsigned num_elements);
- void add_array(const T* ptr, unsigned num_elem)
- {
- while(num_elem--)
- {
- add(*ptr++);
- }
- }
- template<class DataAccessor> void add_data(DataAccessor& data)
- {
- while(data.size())
- {
- add(*data);
- ++data;
- }
- }
- void cut_at(unsigned size)
- {
- if(size < m_size) m_size = size;
- }
- unsigned size() const { return m_size; }
- const T& operator [] (unsigned i) const
- {
- return m_blocks[i >> block_shift][i & block_mask];
- }
- T& operator [] (unsigned i)
- {
- return m_blocks[i >> block_shift][i & block_mask];
- }
- const T& at(unsigned i) const
- {
- return m_blocks[i >> block_shift][i & block_mask];
- }
- T& at(unsigned i)
- {
- return m_blocks[i >> block_shift][i & block_mask];
- }
- T value_at(unsigned i) const
- {
- return m_blocks[i >> block_shift][i & block_mask];
- }
- const T& curr(unsigned idx) const
- {
- return (*this)[idx];
- }
- T& curr(unsigned idx)
- {
- return (*this)[idx];
- }
- const T& prev(unsigned idx) const
- {
- return (*this)[(idx + m_size - 1) % m_size];
- }
- T& prev(unsigned idx)
- {
- return (*this)[(idx + m_size - 1) % m_size];
- }
- const T& next(unsigned idx) const
- {
- return (*this)[(idx + 1) % m_size];
- }
- T& next(unsigned idx)
- {
- return (*this)[(idx + 1) % m_size];
- }
- const T& last() const
- {
- return (*this)[m_size - 1];
- }
- T& last()
- {
- return (*this)[m_size - 1];
- }
- unsigned byte_size() const;
- void serialize(int8u* ptr) const;
- void deserialize(const int8u* data, unsigned byte_size);
- void deserialize(unsigned start, const T& empty_val,
- const int8u* data, unsigned byte_size);
- template<class ByteAccessor>
- void deserialize(ByteAccessor data)
- {
- remove_all();
- unsigned elem_size = data.size() / sizeof(T);
- for(unsigned i = 0; i < elem_size; ++i)
- {
- int8u* ptr = (int8u*)data_ptr();
- for(unsigned j = 0; j < sizeof(T); ++j)
- {
- *ptr++ = *data;
- ++data;
- }
- ++m_size;
- }
- }
- template<class ByteAccessor>
- void deserialize(unsigned start, const T& empty_val, ByteAccessor data)
- {
- while(m_size < start)
- {
- add(empty_val);
- }
- unsigned elem_size = data.size() / sizeof(T);
- for(unsigned i = 0; i < elem_size; ++i)
- {
- int8u* ptr;
- if(start + i < m_size)
- {
- ptr = (int8u*)(&((*this)[start + i]));
- }
- else
- {
- ptr = (int8u*)data_ptr();
- ++m_size;
- }
- for(unsigned j = 0; j < sizeof(T); ++j)
- {
- *ptr++ = *data;
- ++data;
- }
- }
- }
- const T* block(unsigned nb) const { return m_blocks[nb]; }
- private:
- void allocate_block(unsigned nb);
- T* data_ptr();
- unsigned m_size;
- unsigned m_num_blocks;
- unsigned m_max_blocks;
- T** m_blocks;
- unsigned m_block_ptr_inc;
- };
- //------------------------------------------------------------------------
- template<class T, unsigned S> pod_bvector<T, S>::~pod_bvector()
- {
- if(m_num_blocks)
- {
- T** blk = m_blocks + m_num_blocks - 1;
- while(m_num_blocks--)
- {
- pod_allocator<T>::deallocate(*blk, block_size);
- --blk;
- }
- }
- pod_allocator<T*>::deallocate(m_blocks, m_max_blocks);
- }
- //------------------------------------------------------------------------
- template<class T, unsigned S>
- void pod_bvector<T, S>::free_tail(unsigned size)
- {
- if(size < m_size)
- {
- unsigned nb = (size + block_mask) >> block_shift;
- while(m_num_blocks > nb)
- {
- pod_allocator<T>::deallocate(m_blocks[--m_num_blocks], block_size);
- }
- if(m_num_blocks == 0)
- {
- pod_allocator<T*>::deallocate(m_blocks, m_max_blocks);
- m_blocks = 0;
- m_max_blocks = 0;
- }
- m_size = size;
- }
- }
- //------------------------------------------------------------------------
- template<class T, unsigned S> pod_bvector<T, S>::pod_bvector() :
- m_size(0),
- m_num_blocks(0),
- m_max_blocks(0),
- m_blocks(0),
- m_block_ptr_inc(block_size)
- {
- }
- //------------------------------------------------------------------------
- template<class T, unsigned S>
- pod_bvector<T, S>::pod_bvector(unsigned block_ptr_inc) :
- m_size(0),
- m_num_blocks(0),
- m_max_blocks(0),
- m_blocks(0),
- m_block_ptr_inc(block_ptr_inc)
- {
- }
- //------------------------------------------------------------------------
- template<class T, unsigned S>
- pod_bvector<T, S>::pod_bvector(const pod_bvector<T, S>& v) :
- m_size(v.m_size),
- m_num_blocks(v.m_num_blocks),
- m_max_blocks(v.m_max_blocks),
- m_blocks(v.m_max_blocks ?
- pod_allocator<T*>::allocate(v.m_max_blocks) :
- 0),
- m_block_ptr_inc(v.m_block_ptr_inc)
- {
- unsigned i;
- for(i = 0; i < v.m_num_blocks; ++i)
- {
- m_blocks[i] = pod_allocator<T>::allocate(block_size);
- memcpy(m_blocks[i], v.m_blocks[i], block_size * sizeof(T));
- }
- }
- //------------------------------------------------------------------------
- template<class T, unsigned S>
- const pod_bvector<T, S>&
- pod_bvector<T, S>::operator = (const pod_bvector<T, S>& v)
- {
- unsigned i;
- for(i = m_num_blocks; i < v.m_num_blocks; ++i)
- {
- allocate_block(i);
- }
- for(i = 0; i < v.m_num_blocks; ++i)
- {
- memcpy(m_blocks[i], v.m_blocks[i], block_size * sizeof(T));
- }
- m_size = v.m_size;
- return *this;
- }
- //------------------------------------------------------------------------
- template<class T, unsigned S>
- void pod_bvector<T, S>::allocate_block(unsigned nb)
- {
- if(nb >= m_max_blocks)
- {
- T** new_blocks = pod_allocator<T*>::allocate(m_max_blocks + m_block_ptr_inc);
- if(m_blocks)
- {
- memcpy(new_blocks,
- m_blocks,
- m_num_blocks * sizeof(T*));
- pod_allocator<T*>::deallocate(m_blocks, m_max_blocks);
- }
- m_blocks = new_blocks;
- m_max_blocks += m_block_ptr_inc;
- }
- m_blocks[nb] = pod_allocator<T>::allocate(block_size);
- m_num_blocks++;
- }
- //------------------------------------------------------------------------
- template<class T, unsigned S>
- inline T* pod_bvector<T, S>::data_ptr()
- {
- unsigned nb = m_size >> block_shift;
- if(nb >= m_num_blocks)
- {
- allocate_block(nb);
- }
- return m_blocks[nb] + (m_size & block_mask);
- }
- //------------------------------------------------------------------------
- template<class T, unsigned S>
- inline void pod_bvector<T, S>::add(const T& val)
- {
- *data_ptr() = val;
- ++m_size;
- }
- //------------------------------------------------------------------------
- template<class T, unsigned S>
- inline void pod_bvector<T, S>::remove_last()
- {
- if(m_size) --m_size;
- }
- //------------------------------------------------------------------------
- template<class T, unsigned S>
- void pod_bvector<T, S>::modify_last(const T& val)
- {
- remove_last();
- add(val);
- }
- //------------------------------------------------------------------------
- template<class T, unsigned S>
- int pod_bvector<T, S>::allocate_continuous_block(unsigned num_elements)
- {
- if(num_elements < block_size)
- {
- data_ptr(); // Allocate initial block if necessary
- unsigned rest = block_size - (m_size & block_mask);
- unsigned index;
- if(num_elements <= rest)
- {
- // The rest of the block is good, we can use it
- //-----------------
- index = m_size;
- m_size += num_elements;
- return index;
- }
- // New block
- //---------------
- m_size += rest;
- data_ptr();
- index = m_size;
- m_size += num_elements;
- return index;
- }
- return -1; // Impossible to allocate
- }
- //------------------------------------------------------------------------
- template<class T, unsigned S>
- unsigned pod_bvector<T, S>::byte_size() const
- {
- return m_size * sizeof(T);
- }
- //------------------------------------------------------------------------
- template<class T, unsigned S>
- void pod_bvector<T, S>::serialize(int8u* ptr) const
- {
- unsigned i;
- for(i = 0; i < m_size; i++)
- {
- memcpy(ptr, &(*this)[i], sizeof(T));
- ptr += sizeof(T);
- }
- }
- //------------------------------------------------------------------------
- template<class T, unsigned S>
- void pod_bvector<T, S>::deserialize(const int8u* data, unsigned byte_size)
- {
- remove_all();
- byte_size /= sizeof(T);
- for(unsigned i = 0; i < byte_size; ++i)
- {
- T* ptr = data_ptr();
- memcpy(ptr, data, sizeof(T));
- ++m_size;
- data += sizeof(T);
- }
- }
- // Replace or add a number of elements starting from "start" position
- //------------------------------------------------------------------------
- template<class T, unsigned S>
- void pod_bvector<T, S>::deserialize(unsigned start, const T& empty_val,
- const int8u* data, unsigned byte_size)
- {
- while(m_size < start)
- {
- add(empty_val);
- }
- byte_size /= sizeof(T);
- for(unsigned i = 0; i < byte_size; ++i)
- {
- if(start + i < m_size)
- {
- memcpy(&((*this)[start + i]), data, sizeof(T));
- }
- else
- {
- T* ptr = data_ptr();
- memcpy(ptr, data, sizeof(T));
- ++m_size;
- }
- data += sizeof(T);
- }
- }
- //---------------------------------------------------------block_allocator
- // Allocator for arbitrary POD data. Most usable in different cache
- // systems for efficient memory allocations.
- // Memory is allocated with blocks of fixed size ("block_size" in
- // the constructor). If required size exceeds the block size the allocator
- // creates a new block of the required size. However, the most efficient
- // use is when the average reqired size is much less than the block size.
- //------------------------------------------------------------------------
- class block_allocator
- {
- struct block_type
- {
- int8u* data;
- unsigned size;
- };
- public:
- void remove_all()
- {
- if(m_num_blocks)
- {
- block_type* blk = m_blocks + m_num_blocks - 1;
- while(m_num_blocks--)
- {
- pod_allocator<int8u>::deallocate(blk->data, blk->size);
- --blk;
- }
- pod_allocator<block_type>::deallocate(m_blocks, m_max_blocks);
- }
- m_num_blocks = 0;
- m_max_blocks = 0;
- m_blocks = 0;
- m_buf_ptr = 0;
- m_rest = 0;
- }
- ~block_allocator()
- {
- remove_all();
- }
- block_allocator(unsigned block_size, unsigned block_ptr_inc=256-8) :
- m_block_size(block_size),
- m_block_ptr_inc(block_ptr_inc),
- m_num_blocks(0),
- m_max_blocks(0),
- m_blocks(0),
- m_buf_ptr(0),
- m_rest(0)
- {
- }
-
- int8u* allocate(unsigned size, unsigned alignment=1)
- {
- if(size == 0) return 0;
- if(size <= m_rest)
- {
- int8u* ptr = m_buf_ptr;
- if(alignment > 1)
- {
- unsigned align =
- (alignment - unsigned((size_t)ptr) % alignment) % alignment;
- size += align;
- ptr += align;
- if(size <= m_rest)
- {
- m_rest -= size;
- m_buf_ptr += size;
- return ptr;
- }
- allocate_block(size);
- return allocate(size - align, alignment);
- }
- m_rest -= size;
- m_buf_ptr += size;
- return ptr;
- }
- allocate_block(size + alignment - 1);
- return allocate(size, alignment);
- }
- private:
- void allocate_block(unsigned size)
- {
- if(size < m_block_size) size = m_block_size;
- if(m_num_blocks >= m_max_blocks)
- {
- block_type* new_blocks =
- pod_allocator<block_type>::allocate(m_max_blocks + m_block_ptr_inc);
- if(m_blocks)
- {
- memcpy(new_blocks,
- m_blocks,
- m_num_blocks * sizeof(block_type));
- pod_allocator<block_type>::deallocate(m_blocks, m_max_blocks);
- }
- m_blocks = new_blocks;
- m_max_blocks += m_block_ptr_inc;
- }
- m_blocks[m_num_blocks].size = size;
- m_blocks[m_num_blocks].data =
- m_buf_ptr =
- pod_allocator<int8u>::allocate(size);
- m_num_blocks++;
- m_rest = size;
- }
- unsigned m_block_size;
- unsigned m_block_ptr_inc;
- unsigned m_num_blocks;
- unsigned m_max_blocks;
- block_type* m_blocks;
- int8u* m_buf_ptr;
- unsigned m_rest;
- };
- //------------------------------------------------------------------------
- enum quick_sort_threshold_e
- {
- quick_sort_threshold = 9
- };
-
- //-----------------------------------------------------------swap_elements
- template<class T> inline void swap_elements(T& a, T& b)
- {
- T temp = a;
- a = b;
- b = temp;
- }
- //--------------------------------------------------------------quick_sort
- template<class Array, class Less>
- void quick_sort(Array& arr, Less less)
- {
- if(arr.size() < 2) return;
- typename Array::value_type* e1;
- typename Array::value_type* e2;
- int stack[80];
- int* top = stack;
- int limit = arr.size();
- int base = 0;
- for(;;)
- {
- int len = limit - base;
- int i;
- int j;
- int pivot;
- if(len > quick_sort_threshold)
- {
- // we use base + len/2 as the pivot
- pivot = base + len / 2;
- swap_elements(arr[base], arr[pivot]);
- i = base + 1;
- j = limit - 1;
- // now ensure that *i <= *base <= *j
- e1 = &(arr[j]);
- e2 = &(arr[i]);
- if(less(*e1, *e2)) swap_elements(*e1, *e2);
- e1 = &(arr[base]);
- e2 = &(arr[i]);
- if(less(*e1, *e2)) swap_elements(*e1, *e2);
- e1 = &(arr[j]);
- e2 = &(arr[base]);
- if(less(*e1, *e2)) swap_elements(*e1, *e2);
- for(;;)
- {
- do i++; while( less(arr[i], arr[base]) );
- do j--; while( less(arr[base], arr[j]) );
- if( i > j )
- {
- break;
- }
- swap_elements(arr[i], arr[j]);
- }
- swap_elements(arr[base], arr[j]);
- // now, push the largest sub-array
- if(j - base > limit - i)
- {
- top[0] = base;
- top[1] = j;
- base = i;
- }
- else
- {
- top[0] = i;
- top[1] = limit;
- limit = j;
- }
- top += 2;
- }
- else
- {
- // the sub-array is small, perform insertion sort
- j = base;
- i = j + 1;
- for(; i < limit; j = i, i++)
- {
- for(; less(*(e1 = &(arr[j + 1])), *(e2 = &(arr[j]))); j--)
- {
- swap_elements(*e1, *e2);
- if(j == base)
- {
- break;
- }
- }
- }
- if(top > stack)
- {
- top -= 2;
- base = top[0];
- limit = top[1];
- }
- else
- {
- break;
- }
- }
- }
- }
- //------------------------------------------------------remove_duplicates
- // Remove duplicates from a sorted array. It doesn't cut the
- // tail of the array, it just returns the number of remaining elements.
- //-----------------------------------------------------------------------
- template<class Array, class Equal>
- unsigned remove_duplicates(Array& arr, Equal equal)
- {
- if(arr.size() < 2) return arr.size();
- unsigned i, j;
- for(i = 1, j = 1; i < arr.size(); i++)
- {
- typename Array::value_type& e = arr[i];
- if(!equal(e, arr[i - 1]))
- {
- arr[j++] = e;
- }
- }
- return j;
- }
- //--------------------------------------------------------invert_container
- template<class Array> void invert_container(Array& arr)
- {
- int i = 0;
- int j = arr.size() - 1;
- while(i < j)
- {
- swap_elements(arr[i++], arr[j--]);
- }
- }
- //------------------------------------------------------binary_search_pos
- template<class Array, class Value, class Less>
- unsigned binary_search_pos(const Array& arr, const Value& val, Less less)
- {
- if(arr.size() == 0) return 0;
- unsigned beg = 0;
- unsigned end = arr.size() - 1;
- if(less(val, arr[0])) return 0;
- if(less(arr[end], val)) return end + 1;
- while(end - beg > 1)
- {
- unsigned mid = (end + beg) >> 1;
- if(less(val, arr[mid])) end = mid;
- else beg = mid;
- }
- //if(beg <= 0 && less(val, arr[0])) return 0;
- //if(end >= arr.size() - 1 && less(arr[end], val)) ++end;
- return end;
- }
- //----------------------------------------------------------range_adaptor
- template<class Array> class range_adaptor
- {
- public:
- typedef typename Array::value_type value_type;
- range_adaptor(Array& array, unsigned start, unsigned size) :
- m_array(array), m_start(start), m_size(size)
- {}
- unsigned size() const { return m_size; }
- const value_type& operator [] (unsigned i) const { return m_array[m_start + i]; }
- value_type& operator [] (unsigned i) { return m_array[m_start + i]; }
- const value_type& at(unsigned i) const { return m_array[m_start + i]; }
- value_type& at(unsigned i) { return m_array[m_start + i]; }
- value_type value_at(unsigned i) const { return m_array[m_start + i]; }
- private:
- Array& m_array;
- unsigned m_start;
- unsigned m_size;
- };
- //---------------------------------------------------------------int_less
- inline bool int_less(int a, int b) { return a < b; }
- //------------------------------------------------------------int_greater
- inline bool int_greater(int a, int b) { return a > b; }
- //----------------------------------------------------------unsigned_less
- inline bool unsigned_less(unsigned a, unsigned b) { return a < b; }
- //-------------------------------------------------------unsigned_greater
- inline bool unsigned_greater(unsigned a, unsigned b) { return a > b; }
- }
- #endif
|