From b50c7fe536960a49349475f5c361044b097f24dc Mon Sep 17 00:00:00 2001 From: Graeme Geldenhuys Date: Mon, 27 Feb 2012 19:53:35 +0200 Subject: initial import of AggPas 2.4 RM3 The AggPas demos will not compile at this time, because I have restructured the directories a bit. I wanted a pristine checkin though. The demos will be fixed in the next few commits. --- src/corelib/render/software/agg_array.pas | 1194 +++++++++++++++++++++++++++++ 1 file changed, 1194 insertions(+) create mode 100644 src/corelib/render/software/agg_array.pas (limited to 'src/corelib/render/software/agg_array.pas') diff --git a/src/corelib/render/software/agg_array.pas b/src/corelib/render/software/agg_array.pas new file mode 100644 index 00000000..ad013c9a --- /dev/null +++ b/src/corelib/render/software/agg_array.pas @@ -0,0 +1,1194 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry - Version 2.4 (Public License) +// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) +// +// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3) +// Pascal Port By: Milan Marusinec alias Milano +// milan@marusinec.sk +// http://www.aggpas.org +// Copyright (c) 2005-2006 +// +// 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 +// +// [Pascal Port History] ----------------------------------------------------- +// +// 23.06.2006-Milano: ptrcomp adjustments +// 18.02.2006-MIlano: pod_array_adaptor, quick_sort +// 16.02.2006-Milano: pod_allocator +// 19.12.2005-Milano: pod_deque +// 15.11.2005-Milano: Unit port establishment +// +{ agg_array.pas } +unit + agg_array ; + +INTERFACE + +{$I agg_mode.inc } + +uses + agg_basics ; + +{ TYPES DEFINITION } +type + func_less = function(e1 ,e2 : pointer ) : boolean; + func_equal = function(e1 ,e2 : pointer ) : boolean; + + array_base_ptr = ^array_base; + array_base = object + function size : unsigned; virtual; abstract; + function entry : unsigned; virtual; abstract; + function array_operator(i : unsigned ) : pointer; virtual; abstract; + + function at(i : unsigned ) : pointer; virtual; + + end; + +//----------------------------------------------------------range_adaptor + range_adaptor = object(array_base ) + private + m_array : array_base_ptr; + m_start , + m_size : unsigned; + + public + constructor Construct(array_ : array_base_ptr; start ,size_ : unsigned ); + + function size : unsigned; virtual; + function entry : unsigned; virtual; + function array_operator(i : unsigned ) : pointer; virtual; + + end; + +//-------------------------------------------------------pod_array_adaptor + pod_array_adaptor_ptr = ^pod_array_adaptor; + pod_array_adaptor = object(array_base ) + m_array : pointer; + m_size , + m_entry : unsigned; + + constructor Construct(array_ : pointer; size_ ,entry_ : unsigned ); + + function size : unsigned; virtual; + function entry : unsigned; virtual; + function array_operator(i : unsigned ) : pointer; virtual; + + function at(i : unsigned ) : pointer; virtual; + + end; + +//---------------------------------------------------------pod_auto_array + pod_auto_array_ptr = ^pod_auto_array; + pod_auto_array = object(array_base ) + m_size , + m_entry_sz : unsigned; + + m_array : pointer; + + constructor Construct(size_ ,entry_sz : unsigned ); + destructor Destruct; + + function size : unsigned; virtual; + function entry : unsigned; virtual; + function array_operator(i : unsigned ) : pointer; virtual; + + end; + +//---------------------------------------------------------------pod_array +// A simple class template to store Plain Old Data, a vector +// of a fixed size. The data is continous in memory +//------------------------------------------------------------------------ + pod_array = object(array_base ) + m_entry_sz , + m_size , + m_capacity : unsigned; + + m_array : pointer; + + constructor Construct(entry_sz : unsigned ); overload; + constructor Construct(entry_sz ,size_ : unsigned ); overload; + constructor Create (entry_sz ,size_ : unsigned ); + destructor Destruct; + + procedure allocate(size_ : unsigned; extra_tail : unsigned = 0 ); + procedure resize (new_size : unsigned ); + procedure capacity(cap ,extra_tail : unsigned ); + + procedure zero; + procedure add(v : pointer ); + function data : pointer; + + function size : unsigned; virtual; + function entry : unsigned; virtual; + function array_operator(i : unsigned ) : pointer; virtual; + + end; + + pod_vector = pod_array; + +//---------------------------------------------------------------pod_deque +// 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. +//------------------------------------------------------------------------ + pod_deque_ptr = ^pod_deque; + pod_deque = object(array_base ) + block_shift , + block_size , + block_mask : unsigned; + + m_size , + m_num_blocks , + m_max_blocks , + m_block_ptr_inc : unsigned; + + m_blocks : pointer; + + m_entry_sz : unsigned; + + constructor Construct(entry_sz : unsigned; s_ : unsigned = 6 ); overload; + constructor Construct(block_ptr_inc ,entry_sz : unsigned; s_ : unsigned ); overload; + destructor Destruct; + + procedure remove_all; + procedure remove_last; + + procedure add (val : pointer ); + procedure modify_last(val : pointer ); + + procedure cut_at(size_ : unsigned ); + + function size : unsigned; virtual; + function entry : unsigned; virtual; + + function array_operator (i : unsigned ) : pointer; virtual; + procedure assign_operator(v : pod_deque_ptr ); + + function curr(idx : unsigned ) : pointer; + function prev(idx : unsigned ) : pointer; + function next(idx : unsigned ) : pointer; + function last : pointer; + + function allocate_continuous_block(num_elements : unsigned ) : int; + procedure allocate_block (nb : unsigned ); + + function data_ptr : pointer; + + end; + + pod_bvector_ptr = ^pod_bvector; + pod_bvector = pod_deque; + +//-----------------------------------------------------------pod_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. +//------------------------------------------------------------------------ + pod_alloc_ptr = ^pod_alloc; + pod_alloc = record + ptr : int8u_ptr; + sz : unsigned; + + end; + + pod_allocator = object + m_block_size , + m_block_ptr_inc , + m_num_blocks , + m_max_blocks : unsigned; + + m_blocks : pod_alloc_ptr; + m_buf_ptr : int8u_ptr; + + m_rest : unsigned; + + constructor Construct(block_size : unsigned; block_ptr_inc : unsigned = 256 - 8 ); + destructor Destruct; + + procedure remove_all; + + function allocate(size : unsigned; alignment : unsigned = 1 ) : int8u_ptr; + + procedure allocate_block(size : unsigned ); + + end; + +{ GLOBAL VARIABLES & CONSTANTS } +{ GLOBAL PROCEDURES } + procedure quick_sort (arr : array_base_ptr; less : func_less ); + function remove_duplicates(arr : array_base_ptr; equal : func_equal ) : unsigned; + + function int_less (a ,b : pointer ) : boolean; + function int_greater(a ,b : pointer ) : boolean; + + function unsigned_less (a ,b : pointer ) : boolean; + function unsigned_greater(a ,b : pointer ) : boolean; + +IMPLEMENTATION +{ LOCAL VARIABLES & CONSTANTS } +{ QUICK_SORT } +procedure quick_sort; +const + quick_sort_threshold = 9; + +type + int80_ptr = ^int80; + int80 = array[0..79 ] of int; + +var + temp ,e1 ,e2 : pointer; + + swap : unsigned; + + stack : int80; + + top : int80_ptr; + + limit ,base ,len ,i ,j ,pivot : int; + +begin + if arr.size < 2 then + exit; + + agg_getmem(temp ,arr.entry ); + + swap :=arr.entry; + top :=@stack; + limit:=arr.size; + base :=0; + + repeat + len:=limit - base; + + if len > quick_sort_threshold then + begin + // we use base + len/2 as the pivot + pivot:=base + len div 2; + + // swap_elements(arr[base], arr[pivot]); + move(arr.at(base )^ ,temp^ ,swap ); + move(arr.at(pivot )^ ,arr.at(base )^ ,swap ); + move(temp^ ,arr.at(pivot )^ ,swap ); + + i:=base + 1; + j:=limit - 1; + + // now ensure that *i <= *base <= *j + e1:=arr.at(j ); + e2:=arr.at(i ); + + if less(e1 ,e2 ) then + begin + // swap_elements(*e1, *e2); + move(e1^ ,temp^ ,swap ); + move(e2^ ,e1^ ,swap ); + move(temp^ ,e2^ ,swap ); + + end; + + e1:=arr.at(base ); + e2:=arr.at(i ); + + if less(e1 ,e2 ) then + begin + // swap_elements(*e1, *e2); + move(e1^ ,temp^ ,swap ); + move(e2^ ,e1^ ,swap ); + move(temp^ ,e2^ ,swap ); + + end; + + e1:=arr.at(j ); + e2:=arr.at(base ); + + if less(e1 ,e2 ) then + begin + // swap_elements(*e1, *e2); + move(e1^ ,temp^ ,swap ); + move(e2^ ,e1^ ,swap ); + move(temp^ ,e2^ ,swap ); + + end; + + repeat + repeat + inc(i ) + + until not less(arr.at(i ) ,arr.at(base ) ); + + repeat + dec(j ); + + until not less(arr.at(base ) ,arr.at(j ) ); + + if i > j then + break; + + // swap_elements(arr[i], arr[j]); + move(arr.at(i )^ ,temp^ ,swap ); + move(arr.at(j )^ ,arr.at(i )^ ,swap ); + move(temp^ ,arr.at(j )^ ,swap ); + + until false; + + // swap_elements(arr[base], arr[j]); + move(arr.at(base )^ ,temp^ ,swap ); + move(arr.at(j )^ ,arr.at(base )^ ,swap ); + move(temp^ ,arr.at(j )^ ,swap ); + + // now, push the largest sub-array + if j - base > limit - i then + begin + top^[0 ]:=base; + top^[1 ]:=j; + base :=i; + + end + else + begin + top^[0 ]:=i; + top^[1 ]:=limit; + limit :=j; + + end; + + inc(ptrcomp(top ) ,2 * sizeof(int ) ); + + end + else + begin + // the sub-array is small, perform insertion sort + j:=base; + i:=j + 1; + + while i < limit do + begin + e1:=arr.at(j + 1 ); + e2:=arr.at(j ); + + while less(e1 ,e2 ) do + begin + // swap_elements(*e1, *e2); + move(e1^ ,temp^ ,swap ); + move(e2^ ,e1^ ,swap ); + move(temp^ ,e2^ ,swap ); + + if j = base then + break; + + dec(j ); + + e1:=arr.at(j + 1 ); + e2:=arr.at(j ); + + end; + + j:=i; + + inc(i ); + + end; + + if ptrcomp(top ) > ptrcomp(@stack ) then + begin + dec(ptrcomp(top ) ,2 * sizeof(int ) ); + + base :=top^[0 ]; + limit:=top^[1 ]; + + end + else + break; + + end; + + until false; + + agg_freemem(temp ,arr.entry ); + +end; + +{ 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. +function remove_duplicates(arr : array_base_ptr; equal : func_equal ) : unsigned; +var + i ,j : unsigned; + + e : pointer; + +begin + if arr.size < 2 then + begin + result:=arr.size; + + exit; + + end; + + i:=1; + j:=1; + + while i < arr.size do + begin + e:=arr.array_operator(i ); + + if not equal(e ,arr.array_operator(i - 1 ) ) then + begin + move(e^ ,arr.array_operator(j )^ ,arr.entry ); + inc (j ); + + end; + + inc(i ); + + end; + + result:=j; + +end; + +{ INT_LESS } +function int_less(a ,b : pointer ) : boolean; +begin + result:=int_ptr(a )^ < int_ptr(b )^; + +end; + +{ INT_GREATER } +function int_greater(a ,b : pointer ) : boolean; +begin + result:=int_ptr(a )^ > int_ptr(b )^; + +end; + +{ UNSIGNED_LESS } +function unsigned_less(a ,b : pointer ) : boolean; +begin + result:=unsigned_ptr(a )^ < unsigned_ptr(b )^; + +end; + +{ UNSIGNED_GREATER } +function unsigned_greater(a ,b : pointer ) : boolean; +begin + result:=unsigned_ptr(a )^ > unsigned_ptr(b )^; + +end; + +{ UNIT IMPLEMENTATION } +{ AT } +function array_base.at; +begin + at:=array_operator(i ); + +end; + +{ CONSTRUCT } +constructor range_adaptor.Construct(array_ : array_base_ptr; start ,size_ : unsigned ); +begin + m_array:=array_; + m_start:=start; + m_size :=size_; + +end; + +{ SIZE } +function range_adaptor.size : unsigned; +begin + result:=m_size; + +end; + +{ ENTRY } +function range_adaptor.entry : unsigned; +begin + result:=m_array.entry; + +end; + +{ ARRAY_OPERATOR } +function range_adaptor.array_operator(i : unsigned ) : pointer; +begin + result:=m_array.array_operator(m_start + i ); + +end; + +{ CONSTRUCT } +constructor pod_array_adaptor.Construct; +begin + m_array:=array_; + m_size :=size_; + m_entry:=entry_; + +end; + +{ SIZE } +function pod_array_adaptor.size; +begin + result:=m_size; + +end; + +{ ENTRY } +function pod_array_adaptor.entry; +begin + result:=m_entry; + +end; + +{ ARRAY_OPERATOR } +function pod_array_adaptor.array_operator; +begin + result:=pointer(ptrcomp(m_array ) + i * sizeof(m_entry ) ); + +end; + +{ AT } +function pod_array_adaptor.at; +begin + result:=pointer(ptrcomp(m_array ) + i * m_entry ); + +end; + +{ CONSTRUCT } +constructor pod_auto_array.Construct; +begin + m_size :=size_; + m_entry_sz:=entry_sz; + + agg_getmem(m_array ,m_size * m_entry_sz ); + +end; + +{ DESTRUCT } +destructor pod_auto_array.Destruct; +begin + agg_freemem(m_array ,m_size * m_entry_sz ); + +end; + +{ SIZE } +function pod_auto_array.size; +begin + result:=m_size; + +end; + +{ ENTRY } +function pod_auto_array.entry; +begin + result:=m_entry_sz; + +end; + +{ ARRAY_OPERATOR } +function pod_auto_array.array_operator; +begin + result:=pointer(ptrcomp(m_array ) + i * m_entry_sz ); + +end; + +{ CONSTRUCT } +constructor pod_array.Construct(entry_sz : unsigned ); +begin + m_entry_sz:=entry_sz; + m_size :=0; + m_capacity:=0; + + m_array:=NIL; + +end; + +{ CONSTRUCT } +constructor pod_array.Construct(entry_sz ,size_ : unsigned ); +begin + Construct(entry_sz ); + allocate (size_ ); + +end; + +{ CREATE } +constructor pod_array.Create(entry_sz ,size_ : unsigned ); +begin + Construct(entry_sz ); + capacity (size_ ,0 ); + +end; + +{ DESTRUCT } +destructor pod_array.Destruct; +begin + if m_array <> NIL then + agg_freemem(m_array ,m_capacity * m_entry_sz ); + +end; + +{ ALLOCATE } +// Allocate n elements. All data is lost, +// but elements can be accessed in range 0...size-1. +procedure pod_array.allocate; +begin + capacity(size_ ,extra_tail ); + + m_size:=size_; + +end; + +{ RESIZE } +// Resize keeping the content. +procedure pod_array.resize; +var + buff : pointer; + +begin + if new_size > m_size then + if new_size > m_capacity then + begin + agg_getmem(buff ,new_size * m_entry_sz ); + + if m_array <> NIL then + begin + move(m_array^ ,buff^ ,m_size * m_entry_sz ); + + agg_freemem(m_array ,m_capacity * m_entry_sz ); + + end; + + m_array :=buff; + m_capacity:=new_size; + + end + else + else + m_size:=new_size; + +end; + +{ CAPACITY } +procedure pod_array.capacity; +begin + m_size:=0; + + if cap > m_capacity then + begin + agg_freemem(m_array ,m_capacity * m_entry_sz ); + + m_capacity:=cap + extra_tail; + + if m_capacity > 0 then + agg_getmem(m_array ,m_capacity * m_entry_sz ) + else + m_array:=0; + + end; + +end; + +{ ZERO } +procedure pod_array.zero; +begin + fillchar(m_array^ ,m_entry_sz * m_size ,0 ); + +end; + +{ ADD } +procedure pod_array.add(v : pointer ); +begin + move(v^ ,pointer(ptrcomp(m_array ) + m_size * m_entry_sz )^ ,m_entry_sz ); + inc (m_size ); + +end; + +{ DATA } +function pod_array.data; +begin + result:=m_array; + +end; + +{ SIZE } +function pod_array.size; +begin + result:=m_size; + +end; + +{ ENTRY } +function pod_array.entry; +begin + result:=m_entry_sz; + +end; + +{ ARRAY_OPERATOR } +function pod_array.array_operator(i : unsigned ) : pointer; +begin + result:=pointer(ptrcomp(m_array ) + i * m_entry_sz ); + +end; + +{ CONSTRUCT } +constructor pod_deque.Construct(entry_sz : unsigned; s_ : unsigned = 6 ); +begin + block_shift:=s_; + block_size :=1 shl block_shift; + block_mask :=block_size - 1; + + m_size :=0; + m_num_blocks :=0; + m_max_blocks :=0; + m_blocks :=0; + m_block_ptr_inc:=block_size; + + m_entry_sz:=entry_sz; + +end; + +{ CONSTRUCT } +constructor pod_deque.Construct(block_ptr_inc ,entry_sz : unsigned; s_ : unsigned ); +begin + Construct(entry_sz ,s_ ); + + m_block_ptr_inc:=block_ptr_inc; + +end; + +{ DESTRUCT } +destructor pod_deque.Destruct; +var + blk : pointer; + +begin + if m_num_blocks <> 0 then + begin + blk:=pointer(ptrcomp(m_blocks ) + (m_num_blocks - 1 ) * sizeof(pointer ) ); + + while m_num_blocks <> 0 do + begin + agg_freemem(p32(blk^ ).ptr ,block_size * m_entry_sz ); + + dec(ptrcomp(blk ) ,sizeof(pointer ) ); + dec(m_num_blocks ); + + end; + + agg_freemem(m_blocks ,m_max_blocks * sizeof(pointer ) ); + + end; + +end; + +{ REMOVE_ALL } +procedure pod_deque.remove_all; +begin + m_size:=0; + +end; + +{ REMOVE_LAST } +procedure pod_deque.remove_last; +begin + if m_size <> 0 then + dec(m_size ); + +end; + +{ ADD } +procedure pod_deque.add; +var + p : pointer; + +begin + p:=data_ptr; + + move(val^ ,p^ ,m_entry_sz ); + inc (m_size ); + +end; + +{ MODIFY_LAST } +procedure pod_deque.modify_last; +begin + remove_last; + add(val ); + +end; + +{ CUT_AT } +procedure pod_deque.cut_at(size_ : unsigned ); +begin + if size_ < m_size then + m_size:=size_; + +end; + +{ SIZE } +function pod_deque.size; +begin + result:=m_size; + +end; + +{ ENTRY } +function pod_deque.entry; +begin + result:=m_entry_sz; + +end; + +{ ARRAY_OPERATOR } +function pod_deque.array_operator; +begin + result:= + pointer( + p32(pointer(ptrcomp(m_blocks ) + (i shr block_shift ) * sizeof(pointer ) )^ ).int + + (i and block_mask ) * m_entry_sz ); + +end; + +{ ASSIGN_OPERATOR } +procedure pod_deque.assign_operator; +var + i : unsigned; + src , + dst : pointer; + +begin + Destruct; + + block_shift:=v.block_shift; + block_size :=v.block_size; + block_mask :=v.block_mask; + + m_size :=v.m_size; + m_entry_sz:=v.m_entry_sz; + + m_num_blocks:=v.m_num_blocks; + m_max_blocks:=v.m_max_blocks; + + m_block_ptr_inc:=v.m_block_ptr_inc; + + if m_max_blocks <> 0 then + agg_getmem(m_blocks ,m_max_blocks * sizeof(pointer ) ) + else + m_blocks:=NIL; + + + src:=v.m_blocks; + dst:=m_blocks; + i :=0; + + while i < m_num_blocks do + begin + agg_getmem(p32(dst^ ).ptr ,block_size * m_entry_sz ); + + move( + p32(src^ ).ptr^ , + p32(dst^ ).ptr^ , + block_size * m_entry_sz ); + + inc(ptrcomp(src ) ,sizeof(pointer ) ); + inc(ptrcomp(dst ) ,sizeof(pointer ) ); + inc(i ); + + end; + +end; + +{ CURR } +function pod_deque.curr; +begin + result:=array_operator(idx ); + +end; + +{ PREV } +function pod_deque.prev; +begin + result:=array_operator((idx + m_size - 1 ) mod m_size ); + +end; + +{ NEXT } +function pod_deque.next; +begin + result:=array_operator((idx + 1 ) mod m_size ); + +end; + +{ LAST } +function pod_deque.last : pointer; +begin + result:=array_operator(m_size - 1 ); + +end; + +{ ALLOCATE_CONTINUOUS_BLOCK } +function pod_deque.allocate_continuous_block; +var + rest ,index : unsigned; + +begin + if num_elements < block_size then + begin + data_ptr; // Allocate initial block if necessary + + rest:=block_size - (m_size and block_mask ); + + if num_elements <= rest then + begin + // The rest of the block is good, we can use it + index:=m_size; + + inc(m_size ,num_elements ); + + result:=index; + + exit; + + end; + + // New block + inc(m_size ,rest ); + + data_ptr; + + index:=m_size; + + inc(m_size ,num_elements ); + + result:=index; + + exit; + + end; + + result:=-1; // Impossible to allocate + +end; + +{ ALLOCATE_BLOCK } +procedure pod_deque.allocate_block; +var + new_blocks : pointer; + +begin + if nb >= m_max_blocks then + begin + agg_getmem(new_blocks ,(m_max_blocks + m_block_ptr_inc ) * sizeof(pointer ) ); + + if m_blocks <> NIL then + begin + move( + m_blocks^ , + new_blocks^ , + m_num_blocks * sizeof(pointer ) ); + + agg_freemem(m_blocks ,m_max_blocks * sizeof(pointer ) ); + + end; + + m_blocks:=new_blocks; + + inc(m_max_blocks ,m_block_ptr_inc ); + + end; + + agg_getmem( + p32(pointer(ptrcomp(m_blocks ) + nb * sizeof(pointer ) )^ ).ptr , + block_size * m_entry_sz ); + + inc(m_num_blocks ); + +end; + +{ DATA_PTR } +function pod_deque.data_ptr; +var + nb : unsigned; + +begin + nb:=m_size shr block_shift; + + if nb >= m_num_blocks then + allocate_block(nb ); + + result:= + pointer( + p32(pointer(ptrcomp(m_blocks ) + nb * sizeof(pointer ) )^ ).int + + (m_size and block_mask ) * m_entry_sz ); + +end; + +{ CONSTRUCT } +constructor pod_allocator.Construct; +begin + m_block_size :=block_size; + m_block_ptr_inc:=block_ptr_inc; + + m_num_blocks:=0; + m_max_blocks:=0; + + m_blocks :=NIL; + m_buf_ptr:=NIL; + m_rest :=0; + +end; + +{ DESTRUCT } +destructor pod_allocator.Destruct; +begin + remove_all; + +end; + +{ REMOVE_ALL } +procedure pod_allocator.remove_all; +var + blk : pod_alloc_ptr; + +begin + if m_num_blocks <> 0 then + begin + blk:=pod_alloc_ptr(ptrcomp(m_blocks ) + (m_num_blocks - 1 ) * sizeof(pod_alloc ) ); + + while m_num_blocks <> 0 do + begin + agg_freemem(pointer(blk.ptr ) ,blk.sz ); + + dec(ptrcomp(blk ) ,sizeof(pod_alloc ) ); + dec(m_num_blocks ); + + end; + + agg_freemem(pointer(m_blocks ) ,m_max_blocks * sizeof(pod_alloc ) ); + + end; + + m_num_blocks:=0; + m_max_blocks:=0; + + m_blocks :=NIL; + m_buf_ptr:=NIL; + m_rest :=0; + +end; + +{ ALLOCATE } +function pod_allocator.allocate; +var + ptr : int8u_ptr; + align : unsigned; + +begin + if size = 0 then + begin + result:=0; + + exit; + + end; + + if size <= m_rest then + begin + ptr:=m_buf_ptr; + + if alignment > 1 then + begin + align:=(alignment - unsigned(int32u(ptr ) ) mod alignment ) mod alignment; + + inc(size ,align ); + inc(ptrcomp(ptr ) ,align ); + + if size <= m_rest then + begin + dec(m_rest ,size ); + inc(ptrcomp(m_buf_ptr ) ,size ); + + result:=ptr; + + exit; + + end; + + allocate_block(size ); + + result:=allocate(size - align ,alignment ); + + exit; + + end; + + dec(m_rest ,size ); + inc(ptrcomp(m_buf_ptr ) ,size ); + + result:=ptr; + + exit; + + end; + + allocate_block(size + alignment - 1 ); + + result:=allocate(size ,alignment ); + +end; + +{ ALLOCATE_BLOCK } +procedure pod_allocator.allocate_block; +var + new_blocks : pod_alloc_ptr; + +begin + if size < m_block_size then + size:=m_block_size; + + if m_num_blocks >= m_max_blocks then + begin + agg_getmem(pointer(new_blocks ) ,(m_max_blocks + m_block_ptr_inc ) * sizeof(pod_alloc ) ); + + if m_blocks <> NIL then + begin + move(m_blocks^ ,new_blocks^ ,m_num_blocks * sizeof(pod_alloc ) ); + + agg_freemem(pointer(m_blocks ) ,m_max_blocks * sizeof(pod_alloc ) ); + + end; + + m_blocks:=new_blocks; + + inc(m_max_blocks ,m_block_ptr_inc ); + + end; + + agg_getmem(pointer(m_buf_ptr ) ,size * sizeof(int8u ) ); + + pod_alloc_ptr(ptrcomp(m_blocks ) + m_num_blocks * sizeof(pod_alloc ) ).ptr:=m_buf_ptr; + pod_alloc_ptr(ptrcomp(m_blocks ) + m_num_blocks * sizeof(pod_alloc ) ).sz :=size; + + inc(m_num_blocks ); + + m_rest:=size; + +end; + +END. + -- cgit v1.2.3-70-g09d2