1 //Modified by plugwash for 64 bit support
\r
5 Copyright (C) 1998 by Jacques Nomssi Nzali
\r
6 For conditions of distribution and use, see copyright notice in readme.paszlib
\r
13 { Type declarations }
\r
16 {Byte = usigned char; 8 bits}
\r
31 uInt = longint; { 16 bits or more }
\r
34 uInt = cardinal; { 16 bits or more }
\r
43 uLong = LongInt; { 32 bits or more }
\r
58 { a pointer to integer casting is used to do pointer arithmetic.
\r
59 ptr2int must be an integer type and sizeof(ptr2int) must be less
\r
60 than sizeof(pointer) - Nomssi }
\r
64 MaxMemBlock = $FFFF;
\r
66 MaxMemBlock = MaxInt;
\r
70 zByteArray = array[0..(MaxMemBlock div SizeOf(Bytef))-1] of Bytef;
\r
71 pzByteArray = ^zByteArray;
\r
73 zIntfArray = array[0..(MaxMemBlock div SizeOf(Intf))-1] of Intf;
\r
74 pzIntfArray = ^zIntfArray;
\r
76 zuIntArray = array[0..(MaxMemBlock div SizeOf(uInt))-1] of uInt;
\r
77 PuIntArray = ^zuIntArray;
\r
79 { Type declarations - only for deflate }
\r
95 zuchfArray = zByteArray;
\r
96 puchfArray = ^zuchfArray;
\r
98 zushfArray = array[0..(MaxMemBlock div SizeOf(ushf))-1] of ushf;
\r
99 pushfArray = ^zushfArray;
\r
101 procedure zmemcpy(destp : pBytef; sourcep : pBytef; len : uInt);
\r
102 function zmemcmp(s1p, s2p : pBytef; len : uInt) : int;
\r
103 procedure zmemzero(destp : pBytef; len : uInt);
\r
104 procedure zcfree(opaque : voidpf; ptr : voidpf);
\r
105 function zcalloc (opaque : voidpf; items : uInt; size : uInt) : voidpf;
\r
136 { reduce your application memory footprint with $M before using this }
\r
137 function dosAlloc (Size : Longint) : Pointer;
\r
141 regs.bx := (Size + 15) div 16; { number of 16-bytes-paragraphs }
\r
142 regs.ah := $48; { Allocate memory block }
\r
144 if regs.Flags and FCarry <> 0 then
\r
147 DosAlloc := Ptr(regs.ax, 0);
\r
151 function dosFree(P : pointer) : boolean;
\r
156 regs.bx := Seg(P^); { segment }
\r
157 if Ofs(P) <> 0 then
\r
159 regs.ah := $49; { Free memory block }
\r
161 dosFree := (regs.Flags and FCarry = 0);
\r
171 {$define HEAP_LIST}
\r
174 {$IFDEF HEAP_LIST} {--- to avoid Mark and Release --- }
\r
176 MaxAllocEntries = 50;
\r
184 allocatedCount : 0..MaxAllocEntries = 0;
\r
186 allocatedList : array[0..MaxAllocEntries-1] of TMemRec;
\r
188 function NewAllocation(ptr0, ptr : pointer; memsize : longint) : boolean;
\r
190 if (allocatedCount < MaxAllocEntries) and (ptr0 <> NIL) then
\r
192 with allocatedList[allocatedCount] do
\r
198 Inc(allocatedCount); { we don't check for duplicate }
\r
199 NewAllocation := TRUE;
\r
202 NewAllocation := FALSE;
\r
208 { The code below is extremely version specific to the TP 6/7 heap manager!!}
\r
210 PFreeRec = ^TFreeRec;
\r
219 procedure IncPtr(var p:pointer;count:word);
\r
220 { Increments pointer }
\r
222 inc(LH(p).L,count);
\r
223 if LH(p).L < count then
\r
224 inc(LH(p).H,SelectorInc); { $1000 }
\r
227 procedure DecPtr(var p:pointer;count:word);
\r
228 { decrements pointer }
\r
230 if count > LH(p).L then
\r
231 dec(LH(p).H,SelectorInc);
\r
232 dec(LH(p).L,Count);
\r
235 procedure IncPtrLong(var p:pointer;count:longint);
\r
236 { Increments pointer; assumes count > 0 }
\r
238 inc(LH(p).H,SelectorInc*LH(count).H);
\r
239 inc(LH(p).L,LH(Count).L);
\r
240 if LH(p).L < LH(count).L then
\r
241 inc(LH(p).H,SelectorInc);
\r
244 procedure DecPtrLong(var p:pointer;count:longint);
\r
245 { Decrements pointer; assumes count > 0 }
\r
247 if LH(count).L > LH(p).L then
\r
248 dec(LH(p).H,SelectorInc);
\r
249 dec(LH(p).L,LH(Count).L);
\r
250 dec(LH(p).H,SelectorInc*LH(Count).H);
\r
252 { The next section is for real mode only }
\r
254 function Normalized(p : pointer) : pointer;
\r
258 count := LH(p).L and $FFF0;
\r
259 Normalized := Ptr(LH(p).H + (count shr 4), LH(p).L and $F);
\r
262 procedure FreeHuge(var p:HugePtr; size : longint);
\r
270 { block := minimum(size, blocksize); }
\r
271 if size > blocksize then
\r
278 IncPtr(p,block); { we may get ptr($xxxx, $fff8) and 31 bytes left }
\r
279 p := Normalized(p); { to free, so we must normalize }
\r
283 function FreeMemHuge(ptr : pointer) : boolean;
\r
285 i : integer; { -1..MaxAllocEntries }
\r
287 FreeMemHuge := FALSE;
\r
288 i := allocatedCount - 1;
\r
291 if (ptr = allocatedList[i].value) then
\r
293 with allocatedList[i] do
\r
294 FreeHuge(orgvalue, size);
\r
296 Move(allocatedList[i+1], allocatedList[i],
\r
297 SizeOf(TMemRec)*(allocatedCount - 1 - i));
\r
298 Dec(allocatedCount);
\r
299 FreeMemHuge := TRUE;
\r
306 procedure GetMemHuge(var p:HugePtr;memsize:Longint);
\r
311 prev,free : PFreeRec;
\r
312 save,temp : pointer;
\r
316 { Handle the easy cases first }
\r
317 if memsize > maxavail then
\r
320 if memsize <= blocksize then
\r
322 getmem(p, memsize);
\r
323 if not NewAllocation(p, p, memsize) then
\r
325 FreeMem(p, memsize);
\r
331 size := memsize + 15;
\r
333 { Find the block that has enough space }
\r
334 prev := PFreeRec(@freeList);
\r
335 free := prev^.next;
\r
336 while (free <> heapptr) and (ptr2int(free^.size) < size) do
\r
339 free := prev^.next;
\r
342 { Now free points to a region with enough space; make it the first one and
\r
343 multiple allocations will be contiguous. }
\r
347 { In TP 6, this works; check against other heap managers }
\r
350 { block := minimum(size, blocksize); }
\r
351 if size > blocksize then
\r
356 getmem(temp,block);
\r
359 { We've got what we want now; just sort things out and restore the
\r
360 free list to normal }
\r
363 if prev^.next <> freelist then
\r
365 prev^.next := freelist;
\r
371 { return pointer with 0 offset }
\r
374 p := Ptr(Seg(p^)+1,0); { hack }
\r
375 if not NewAllocation(temp, p, memsize + 15) then
\r
377 FreeHuge(temp, size);
\r
387 procedure zmemcpy(destp : pBytef; sourcep : pBytef; len : uInt);
\r
389 Move(sourcep^, destp^, len);
\r
392 function zmemcmp(s1p, s2p : pBytef; len : uInt) : int;
\r
400 for j := 0 to pred(len) do
\r
402 if (source^ <> dest^) then
\r
404 zmemcmp := 2*Ord(source^ > dest^)-1;
\r
413 procedure zmemzero(destp : pBytef; len : uInt);
\r
415 FillChar(destp^, len, 0);
\r
418 procedure zcfree(opaque : voidpf; ptr : voidpf);
\r
429 {h :=} GlobalFreePtr(ptr);
\r
438 Handle := GlobalHandle(LH(ptr).H); { HiWord(LongInt(ptr)) }
\r
439 GlobalUnLock(Handle);
\r
440 GlobalFree(Handle);
\r
444 memsize := puIntf(ptr)^;
\r
445 FreeMem(ptr, memsize+SizeOf(uInt));
\r
447 FreeMem(ptr); { Delphi 2,3,4 }
\r
455 function zcalloc (opaque : voidpf; items : uInt; size : uInt) : voidpf;
\r
463 memsize := uLong(items) * size;
\r
465 p := GlobalAllocPtr(gmem_moveable, memsize);
\r
468 p := dosAlloc(memsize);
\r
471 GetMemHuge(p, memsize);
\r
474 Handle := GlobalAlloc(HeapAllocFlags, memsize);
\r
475 p := GlobalLock(Handle);
\r
478 GetMem(p, memsize+SizeOf(uInt));
\r
479 puIntf(p)^:= memsize;
\r
482 GetMem(p, memsize); { Delphi: p := AllocMem(memsize); }
\r
494 { edited from a SWAG posting:
\r
496 In Turbo Pascal 6, the heap is the memory allocated when using the Procedures 'New' and
\r
497 'GetMem'. The heap starts at the address location pointed to by 'Heaporg' and
\r
498 grows to higher addresses as more memory is allocated. The top of the heap,
\r
499 the first address of allocatable memory space above the allocated memory
\r
500 space, is pointed to by 'HeapPtr'.
\r
502 Memory is deallocated by the Procedures 'Dispose' and 'FreeMem'. As memory
\r
503 blocks are deallocated more memory becomes available, but..... When a block
\r
504 of memory, which is not the top-most block in the heap is deallocated, a gap
\r
505 in the heap will appear. to keep track of these gaps Turbo Pascal maintains
\r
506 a so called free list.
\r
508 The Function 'MaxAvail' holds the size of the largest contiguous free block
\r
509 _in_ the heap. The Function 'MemAvail' holds the sum of all free blocks in
\r
512 TP6.0 keeps track of the free blocks by writing a 'free list Record' to the
\r
513 first eight Bytes of the freed memory block! A (TP6.0) free-list Record
\r
514 contains two four Byte Pointers of which the first one points to the next
\r
515 free memory block, the second Pointer is not a Real Pointer but contains the
\r
516 size of the memory block.
\r
520 TP6.0 maintains a linked list with block sizes and Pointers to the _next_
\r
521 free block. An extra heap Variable 'Heapend' designate the end of the heap.
\r
522 When 'HeapPtr' and 'FreeList' have the same value, the free list is empty.
\r
535 ÚÄ>ÃÄÄÄÄÄÄÄÄÄ´ <ÄÄÄÄ
\r
542 ÀÄij Free ³ FreeList
\r