|  | 
 | //---------------------------------------------------------------------------- | 
 | // Anti-Grain Geometry - Version 2.3 | 
 | // 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 <string.h> | 
 |  | 
 | #include "agg_basics.h" | 
 | #include "core/fxcrt/fx_memory.h"  // For FXSYS_* macros. | 
 |  | 
 | namespace pdfium | 
 | { | 
 | namespace agg | 
 | { | 
 | template <class T> | 
 | class pod_array { | 
 | public: | 
 |     typedef T value_type; | 
 |     ~pod_array() | 
 |     { | 
 |         FX_Free(m_array); | 
 |     } | 
 |     pod_array() : m_size(0), m_capacity(0), m_array(0) {} | 
 |     pod_array(unsigned cap, unsigned extra_tail = 0); | 
 |     pod_array(const pod_array<T>&); | 
 |     pod_array<T>& operator = (const pod_array<T>&); | 
 |     void capacity(unsigned cap, unsigned extra_tail = 0); | 
 |     unsigned capacity() const | 
 |     { | 
 |         return m_capacity; | 
 |     } | 
 |     void allocate(unsigned size, unsigned extra_tail = 0); | 
 |     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 inc_size(unsigned size) | 
 |     { | 
 |         m_size += size; | 
 |     } | 
 |     unsigned size()      const | 
 |     { | 
 |         return m_size; | 
 |     } | 
 |     unsigned byte_size() const | 
 |     { | 
 |         return m_size * sizeof(T); | 
 |     } | 
 |     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 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_array<T>::capacity(unsigned cap, unsigned extra_tail) | 
 | { | 
 |     m_size = 0; | 
 |     unsigned full_cap = cap + extra_tail; | 
 |     if(full_cap < cap) { | 
 |         FX_Free(m_array); | 
 |         m_array = 0; | 
 |         m_capacity = 0; | 
 |     } else if(full_cap > m_capacity) { | 
 |         FX_Free(m_array); | 
 |         m_array = FX_Alloc(T, full_cap); | 
 |         m_capacity = full_cap; | 
 |     } | 
 | } | 
 | template<class T> | 
 | void pod_array<T>::allocate(unsigned size, unsigned extra_tail) | 
 | { | 
 |     capacity(size, extra_tail); | 
 |     m_size = size; | 
 | } | 
 | template<class T> | 
 | void pod_array<T>::resize(unsigned new_size) | 
 | { | 
 |     if(new_size > m_size) { | 
 |         if(new_size > m_capacity) { | 
 |             T* data = FX_AllocUninit(T, new_size); | 
 |             memcpy(data, m_array, m_size * sizeof(T)); | 
 |             FX_Free(m_array); | 
 |             m_array = data; | 
 |         } | 
 |     } else { | 
 |         m_size = new_size; | 
 |     } | 
 | } | 
 | template<class T> pod_array<T>::pod_array(unsigned cap, unsigned extra_tail) : | 
 |     m_size(0), m_capacity(cap + extra_tail), m_array(FX_Alloc(T, m_capacity)) {} | 
 | template<class T> pod_array<T>::pod_array(const pod_array<T>& v) : | 
 |     m_size(v.m_size), | 
 |     m_capacity(v.m_capacity), | 
 |     m_array(v.m_capacity ? FX_Alloc(T, v.m_capacity) : 0) | 
 | { | 
 |   memcpy(m_array, v.m_array, sizeof(T) * v.m_size); | 
 | } | 
 | template<class T> pod_array<T>& | 
 | pod_array<T>::operator = (const pod_array<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, unsigned S = 6> class pod_deque  | 
 | { | 
 | public: | 
 |     enum block_scale_e { | 
 |         block_shift = S, | 
 |         block_size  = 1 << block_shift, | 
 |         block_mask  = block_size - 1 | 
 |     }; | 
 |     typedef T value_type; | 
 |     ~pod_deque(); | 
 |     pod_deque(); | 
 |     pod_deque(unsigned block_ptr_inc); | 
 |     pod_deque(const pod_deque<T, S>& v); | 
 |     pod_deque<T, S>& operator = (const pod_deque<T, S>& v); | 
 |     void remove_all() | 
 |     { | 
 |         m_size = 0; | 
 |     } | 
 |     void free_all() | 
 |     { | 
 |         free_tail(0); | 
 |     } | 
 |     void free_tail(unsigned size); | 
 |     void add(const T& 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; | 
 |     const T* block(unsigned nb) const | 
 |     { | 
 |         return m_blocks[nb]; | 
 |     } | 
 | public: | 
 |     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_deque<T, S>::~pod_deque() | 
 | { | 
 |     if(m_num_blocks) { | 
 |         T** blk = m_blocks + m_num_blocks - 1; | 
 |         while(m_num_blocks--) { | 
 |             FX_Free(*blk); | 
 |             --blk; | 
 |         } | 
 |         FX_Free(m_blocks); | 
 |     } | 
 | } | 
 | template<class T, unsigned S> | 
 | void pod_deque<T, S>::free_tail(unsigned size) | 
 | { | 
 |     if(size < m_size) { | 
 |         unsigned nb = (size + block_mask) >> block_shift; | 
 |         while(m_num_blocks > nb) { | 
 |             FX_Free(m_blocks[--m_num_blocks]); | 
 |         } | 
 |         m_size = size; | 
 |     } | 
 | } | 
 | template<class T, unsigned S> pod_deque<T, S>::pod_deque() : | 
 |     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_deque<T, S>::pod_deque(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_deque<T, S>::pod_deque(const pod_deque<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 ? FX_Alloc(T*, 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] = FX_AllocUninit(T, block_size); | 
 |         memcpy(m_blocks[i], v.m_blocks[i], block_size * sizeof(T)); | 
 |     } | 
 | } | 
 | template<class T, unsigned S> | 
 | pod_deque<T, S>& pod_deque<T, S>::operator = (const pod_deque<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_deque<T, S>::allocate_block(unsigned nb) | 
 | { | 
 |     if(nb >= m_max_blocks) { | 
 |         T** new_blocks = FX_Alloc(T*, m_max_blocks + m_block_ptr_inc); | 
 |         if(m_blocks) { | 
 |           memcpy(new_blocks, m_blocks, m_num_blocks * sizeof(T*)); | 
 |           FX_Free(m_blocks); | 
 |         } | 
 |         m_blocks = new_blocks; | 
 |         m_max_blocks += m_block_ptr_inc; | 
 |     } | 
 |     m_blocks[nb] = FX_Alloc(T, block_size); | 
 |     m_num_blocks++; | 
 | } | 
 | template<class T, unsigned S> | 
 | inline T* pod_deque<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_deque<T, S>::add(const T& val) | 
 | { | 
 |     *data_ptr() = val; | 
 |     ++m_size; | 
 | } | 
 | template<class T, unsigned S> | 
 | inline void pod_deque<T, S>::remove_last() | 
 | { | 
 |     if(m_size) { | 
 |         --m_size; | 
 |     } | 
 | } | 
 | template<class T, unsigned S> | 
 | void pod_deque<T, S>::modify_last(const T& val) | 
 | { | 
 |     remove_last(); | 
 |     add(val); | 
 | } | 
 | template<class T, unsigned S> | 
 | int pod_deque<T, S>::allocate_continuous_block(unsigned num_elements) | 
 | { | 
 |     if(num_elements < block_size) { | 
 |         data_ptr(); | 
 |         unsigned rest = block_size - (m_size & block_mask); | 
 |         unsigned index; | 
 |         if(num_elements <= rest) { | 
 |             index = m_size; | 
 |             m_size += num_elements; | 
 |             return index; | 
 |         } | 
 |         m_size += rest; | 
 |         data_ptr(); | 
 |         index = m_size; | 
 |         m_size += num_elements; | 
 |         return index; | 
 |     } | 
 |     return -1; | 
 | } | 
 | template<class T, unsigned S> | 
 | unsigned pod_deque<T, S>::byte_size() const | 
 | { | 
 |     return m_size * sizeof(T); | 
 | } | 
 | class pod_allocator  | 
 | { | 
 | public: | 
 |     void remove_all() | 
 |     { | 
 |         if(m_num_blocks) { | 
 |             int8u** blk = m_blocks + m_num_blocks - 1; | 
 |             while(m_num_blocks--) { | 
 |                 FX_Free(*blk); | 
 |                 --blk; | 
 |             } | 
 |             FX_Free(m_blocks); | 
 |         } | 
 |         m_num_blocks = 0; | 
 |         m_max_blocks = 0; | 
 |         m_blocks = 0; | 
 |         m_buf_ptr = 0; | 
 |         m_rest = 0; | 
 |     } | 
 |     ~pod_allocator() | 
 |     { | 
 |         remove_all(); | 
 |     } | 
 |     pod_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) { | 
 |             int8u** new_blocks = FX_Alloc(int8u*, m_max_blocks + m_block_ptr_inc); | 
 |             if(m_blocks) { | 
 |               memcpy(new_blocks, m_blocks, m_num_blocks * sizeof(int8u*)); | 
 |               FX_Free(m_blocks); | 
 |             } | 
 |             m_blocks = new_blocks; | 
 |             m_max_blocks += m_block_ptr_inc; | 
 |         } | 
 |         m_blocks[m_num_blocks] = m_buf_ptr = FX_Alloc(int8u, size); | 
 |         m_num_blocks++; | 
 |         m_rest = size; | 
 |     } | 
 |     unsigned m_block_size; | 
 |     unsigned m_block_ptr_inc; | 
 |     unsigned m_num_blocks; | 
 |     unsigned m_max_blocks; | 
 |     int8u**  m_blocks; | 
 |     int8u*   m_buf_ptr; | 
 |     unsigned m_rest; | 
 | }; | 
 | enum quick_sort_threshold_e { | 
 |     quick_sort_threshold = 9 | 
 | }; | 
 | template<class T> inline void swap_elements(T& a, T& b) | 
 | { | 
 |     T temp = a; | 
 |     a = b; | 
 |     b = temp; | 
 | } | 
 | } | 
 | }  // namespace pdfium | 
 | #endif |