zutil.pas 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  1. Unit ZUtil;
  2. {
  3. Copyright (C) 1998 by Jacques Nomssi Nzali
  4. For conditions of distribution and use, see copyright notice in readme.txt
  5. }
  6. interface
  7. {$I zconf.inc}
  8. { Type declarations }
  9. type
  10. {Byte = usigned char; 8 bits}
  11. Bytef = byte;
  12. charf = byte;
  13. {$IFDEF FPC}
  14. int = longint;
  15. {$ELSE}
  16. int = integer;
  17. {$ENDIF}
  18. intf = int;
  19. {$IFDEF FPC}
  20. uInt = Cardinal; { 16 bits or more }
  21. {$ELSE}
  22. {$IFDEF MSDOS}
  23. uInt = Word;
  24. {$ENDIF}
  25. {$ENDIF}
  26. uIntf = uInt;
  27. Long = longint;
  28. {$ifdef FPC}
  29. uLong = Cardinal;
  30. {$else}
  31. uLong = LongInt; { 32 bits or more }
  32. {$endif}
  33. uLongf = uLong;
  34. voidp = pointer;
  35. voidpf = voidp;
  36. pBytef = ^Bytef;
  37. pIntf = ^intf;
  38. puIntf = ^uIntf;
  39. puLong = ^uLongf;
  40. ptr2int = uInt;
  41. { a pointer to integer casting is used to do pointer arithmetic.
  42. ptr2int must be an integer type and sizeof(ptr2int) must be less
  43. than sizeof(pointer) - Nomssi }
  44. type
  45. zByteArray = array[0..(MaxInt div SizeOf(Bytef))-1] of Bytef;
  46. pzByteArray = ^zByteArray;
  47. type
  48. zIntfArray = array[0..(MaxInt div SizeOf(Intf))-1] of Intf;
  49. pzIntfArray = ^zIntfArray;
  50. type
  51. zuIntArray = array[0..(MaxInt div SizeOf(uInt))-1] of uInt;
  52. PuIntArray = ^zuIntArray;
  53. { Type declarations - only for deflate }
  54. type
  55. uch = Byte;
  56. uchf = uch; { FAR }
  57. ush = Word;
  58. ushf = ush;
  59. ulg = LongInt;
  60. unsigned = uInt;
  61. pcharf = ^charf;
  62. puchf = ^uchf;
  63. pushf = ^ushf;
  64. type
  65. zuchfArray = zByteArray;
  66. puchfArray = ^zuchfArray;
  67. type
  68. zushfArray = array[0..(MaxInt div SizeOf(ushf))-1] of ushf;
  69. pushfArray = ^zushfArray;
  70. procedure zmemcpy(destp : pBytef; sourcep : pBytef; len : uInt);
  71. function zmemcmp(s1p, s2p : pBytef; len : uInt) : int;
  72. procedure zmemzero(destp : pBytef; len : uInt);
  73. procedure zcfree(opaque : voidpf; ptr : voidpf);
  74. function zcalloc (opaque : voidpf; items : uInt; size : uInt) : voidpf;
  75. implementation
  76. {$ifdef ver80}
  77. {$define Delphi16}
  78. {$endif}
  79. {$ifdef ver70}
  80. {$define HugeMem}
  81. {$endif}
  82. {$ifdef ver60}
  83. {$define HugeMem}
  84. {$endif}
  85. {$IFDEF CALLDOS}
  86. uses
  87. WinDos;
  88. {$ENDIF}
  89. {$IFDEF Delphi16}
  90. uses
  91. WinTypes,
  92. WinProcs;
  93. {$ENDIF}
  94. {$IFNDEF FPC}
  95. {$IFDEF DPMI}
  96. uses
  97. WinAPI;
  98. {$ENDIF}
  99. {$ENDIF}
  100. {$IFDEF CALLDOS}
  101. { reduce your application memory footprint with $M before using this }
  102. function dosAlloc (Size : Longint) : Pointer;
  103. var
  104. regs: TRegisters;
  105. begin
  106. regs.bx := (Size + 15) div 16; { number of 16-bytes-paragraphs }
  107. regs.ah := $48; { Allocate memory block }
  108. msdos(regs);
  109. if regs.Flags and FCarry <> 0 then
  110. DosAlloc := NIL
  111. else
  112. DosAlloc := Ptr(regs.ax, 0);
  113. end;
  114. function dosFree(P : pointer) : boolean;
  115. var
  116. regs: TRegisters;
  117. begin
  118. dosFree := FALSE;
  119. regs.bx := Seg(P^); { segment }
  120. if Ofs(P) <> 0 then
  121. exit;
  122. regs.ah := $49; { Free memory block }
  123. msdos(regs);
  124. dosFree := (regs.Flags and FCarry = 0);
  125. end;
  126. {$ENDIF}
  127. type
  128. LH = record
  129. L, H : word;
  130. end;
  131. {$IFDEF HugeMem}
  132. {$define HEAP_LIST}
  133. {$endif}
  134. {$IFDEF HEAP_LIST} {--- to avoid Mark and Release --- }
  135. const
  136. MaxAllocEntries = 50;
  137. type
  138. TMemRec = record
  139. orgvalue,
  140. value : pointer;
  141. size: longint;
  142. end;
  143. const
  144. allocatedCount : 0..MaxAllocEntries = 0;
  145. var
  146. allocatedList : array[0..MaxAllocEntries-1] of TMemRec;
  147. function NewAllocation(ptr0, ptr : pointer; memsize : longint) : boolean;
  148. begin
  149. if (allocatedCount < MaxAllocEntries) and (ptr0 <> NIL) then
  150. begin
  151. with allocatedList[allocatedCount] do
  152. begin
  153. orgvalue := ptr0;
  154. value := ptr;
  155. size := memsize;
  156. end;
  157. Inc(allocatedCount); { we don't check for duplicate }
  158. NewAllocation := TRUE;
  159. end
  160. else
  161. NewAllocation := FALSE;
  162. end;
  163. {$ENDIF}
  164. {$IFDEF HugeMem}
  165. { The code below is extremely version specific to the TP 6/7 heap manager!!}
  166. type
  167. PFreeRec = ^TFreeRec;
  168. TFreeRec = record
  169. next: PFreeRec;
  170. size: Pointer;
  171. end;
  172. type
  173. HugePtr = voidpf;
  174. procedure IncPtr(var p:pointer;count:word);
  175. { Increments pointer }
  176. begin
  177. inc(LH(p).L,count);
  178. if LH(p).L < count then
  179. inc(LH(p).H,SelectorInc); { $1000 }
  180. end;
  181. procedure DecPtr(var p:pointer;count:word);
  182. { decrements pointer }
  183. begin
  184. if count > LH(p).L then
  185. dec(LH(p).H,SelectorInc);
  186. dec(LH(p).L,Count);
  187. end;
  188. procedure IncPtrLong(var p:pointer;count:longint);
  189. { Increments pointer; assumes count > 0 }
  190. begin
  191. inc(LH(p).H,SelectorInc*LH(count).H);
  192. inc(LH(p).L,LH(Count).L);
  193. if LH(p).L < LH(count).L then
  194. inc(LH(p).H,SelectorInc);
  195. end;
  196. procedure DecPtrLong(var p:pointer;count:longint);
  197. { Decrements pointer; assumes count > 0 }
  198. begin
  199. if LH(count).L > LH(p).L then
  200. dec(LH(p).H,SelectorInc);
  201. dec(LH(p).L,LH(Count).L);
  202. dec(LH(p).H,SelectorInc*LH(Count).H);
  203. end;
  204. { The next section is for real mode only }
  205. function Normalized(p : pointer) : pointer;
  206. var
  207. count : word;
  208. begin
  209. count := LH(p).L and $FFF0;
  210. Normalized := Ptr(LH(p).H + (count shr 4), LH(p).L and $F);
  211. end;
  212. procedure FreeHuge(var p:HugePtr; size : longint);
  213. const
  214. blocksize = $FFF0;
  215. var
  216. block : word;
  217. begin
  218. while size > 0 do
  219. begin
  220. { block := minimum(size, blocksize); }
  221. if size > blocksize then
  222. block := blocksize
  223. else
  224. block := size;
  225. dec(size,block);
  226. freemem(p,block);
  227. IncPtr(p,block); { we may get ptr($xxxx, $fff8) and 31 bytes left }
  228. p := Normalized(p); { to free, so we must normalize }
  229. end;
  230. end;
  231. function FreeMemHuge(ptr : pointer) : boolean;
  232. var
  233. i : integer; { -1..MaxAllocEntries }
  234. begin
  235. FreeMemHuge := FALSE;
  236. i := allocatedCount - 1;
  237. while (i >= 0) do
  238. begin
  239. if (ptr = allocatedList[i].value) then
  240. begin
  241. with allocatedList[i] do
  242. FreeHuge(orgvalue, size);
  243. Move(allocatedList[i+1], allocatedList[i],
  244. SizeOf(TMemRec)*(allocatedCount - 1 - i));
  245. Dec(allocatedCount);
  246. FreeMemHuge := TRUE;
  247. break;
  248. end;
  249. Dec(i);
  250. end;
  251. end;
  252. procedure GetMemHuge(var p:HugePtr;memsize:Longint);
  253. const
  254. blocksize = $FFF0;
  255. var
  256. size : longint;
  257. prev,free : PFreeRec;
  258. save,temp : pointer;
  259. block : word;
  260. begin
  261. p := NIL;
  262. { Handle the easy cases first }
  263. if memsize > maxavail then
  264. exit
  265. else
  266. if memsize <= blocksize then
  267. begin
  268. getmem(p, memsize);
  269. if not NewAllocation(p, p, memsize) then
  270. begin
  271. FreeMem(p, memsize);
  272. p := NIL;
  273. end;
  274. end
  275. else
  276. begin
  277. size := memsize + 15;
  278. { Find the block that has enough space }
  279. prev := PFreeRec(@freeList);
  280. free := prev^.next;
  281. while (free <> heapptr) and (ptr2int(free^.size) < size) do
  282. begin
  283. prev := free;
  284. free := prev^.next;
  285. end;
  286. { Now free points to a region with enough space; make it the first one and
  287. multiple allocations will be contiguous. }
  288. save := freelist;
  289. freelist := free;
  290. { In TP 6, this works; check against other heap managers }
  291. while size > 0 do
  292. begin
  293. { block := minimum(size, blocksize); }
  294. if size > blocksize then
  295. block := blocksize
  296. else
  297. block := size;
  298. dec(size,block);
  299. getmem(temp,block);
  300. end;
  301. { We've got what we want now; just sort things out and restore the
  302. free list to normal }
  303. p := free;
  304. if prev^.next <> freelist then
  305. begin
  306. prev^.next := freelist;
  307. freelist := save;
  308. end;
  309. if (p <> NIL) then
  310. begin
  311. { return pointer with 0 offset }
  312. temp := p;
  313. if Ofs(p^)<>0 Then
  314. p := Ptr(Seg(p^)+1,0); { hack }
  315. if not NewAllocation(temp, p, memsize + 15) then
  316. begin
  317. FreeHuge(temp, size);
  318. p := NIL;
  319. end;
  320. end;
  321. end;
  322. end;
  323. {$ENDIF}
  324. procedure zmemcpy(destp : pBytef; sourcep : pBytef; len : uInt);
  325. begin
  326. Move(sourcep^, destp^, len);
  327. end;
  328. function zmemcmp(s1p, s2p : pBytef; len : uInt) : int;
  329. var
  330. j : uInt;
  331. source,
  332. dest : pBytef;
  333. begin
  334. source := s1p;
  335. dest := s2p;
  336. for j := 0 to pred(len) do
  337. begin
  338. if (source^ <> dest^) then
  339. begin
  340. zmemcmp := 2*Ord(source^ > dest^)-1;
  341. exit;
  342. end;
  343. Inc(source);
  344. Inc(dest);
  345. end;
  346. zmemcmp := 0;
  347. end;
  348. procedure zmemzero(destp : pBytef; len : uInt);
  349. begin
  350. FillChar(destp^, len, 0);
  351. end;
  352. procedure zcfree(opaque : voidpf; ptr : voidpf);
  353. {$ifdef Delphi16}
  354. var
  355. Handle : THandle;
  356. {$endif}
  357. begin
  358. {$IFDEF DPMI}
  359. {h :=} GlobalFreePtr(ptr);
  360. {$ELSE}
  361. {$IFDEF CALL_DOS}
  362. dosFree(ptr);
  363. {$ELSE}
  364. {$ifdef HugeMem}
  365. FreeMemHuge(ptr);
  366. {$else}
  367. {$ifdef Delphi16}
  368. Handle := GlobalHandle(LH(ptr).H); { HiWord(LongInt(ptr)) }
  369. GlobalUnLock(Handle);
  370. GlobalFree(Handle);
  371. {$else}
  372. FreeMem(ptr); { Delphi 2,3,4 }
  373. {$endif}
  374. {$endif}
  375. {$ENDIF}
  376. {$ENDIF}
  377. end;
  378. function zcalloc (opaque : voidpf; items : uInt; size : uInt) : voidpf;
  379. var
  380. p : voidpf;
  381. memsize : LongInt;
  382. {$ifdef Delphi16}
  383. handle : THandle;
  384. {$endif}
  385. begin
  386. memsize := Long(items) * size;
  387. {$IFDEF DPMI}
  388. p := GlobalAllocPtr(gmem_moveable, memsize);
  389. {$ELSE}
  390. {$IFDEF CALLDOS}
  391. p := dosAlloc(memsize);
  392. {$ELSE}
  393. {$ifdef HugeMem}
  394. GetMemHuge(p, memsize);
  395. {$else}
  396. {$ifdef Delphi16}
  397. Handle := GlobalAlloc(HeapAllocFlags, memsize);
  398. p := GlobalLock(Handle);
  399. {$else}
  400. GetMem(p, memsize); { Delphi: p := AllocMem(memsize); }
  401. {$endif}
  402. {$endif}
  403. {$ENDIF}
  404. {$ENDIF}
  405. zcalloc := p;
  406. end;
  407. end.
  408. { edited from a SWAG posting:
  409. In Turbo Pascal 6, the heap is the memory allocated when using the Procedures 'New' and
  410. 'GetMem'. The heap starts at the address location pointed to by 'Heaporg' and
  411. grows to higher addresses as more memory is allocated. The top of the heap,
  412. the first address of allocatable memory space above the allocated memory
  413. space, is pointed to by 'HeapPtr'.
  414. Memory is deallocated by the Procedures 'Dispose' and 'FreeMem'. As memory
  415. blocks are deallocated more memory becomes available, but..... When a block
  416. of memory, which is not the top-most block in the heap is deallocated, a gap
  417. in the heap will appear. to keep track of these gaps Turbo Pascal maintains
  418. a so called free list.
  419. The Function 'MaxAvail' holds the size of the largest contiguous free block
  420. _in_ the heap. The Function 'MemAvail' holds the sum of all free blocks in
  421. the heap.
  422. TP6.0 keeps track of the free blocks by writing a 'free list Record' to the
  423. first eight Bytes of the freed memory block! A (TP6.0) free-list Record
  424. contains two four Byte Pointers of which the first one points to the next
  425. free memory block, the second Pointer is not a Real Pointer but contains the
  426. size of the memory block.
  427. Summary
  428. TP6.0 maintains a linked list with block sizes and Pointers to the _next_
  429. free block. An extra heap Variable 'Heapend' designate the end of the heap.
  430. When 'HeapPtr' and 'FreeList' have the same value, the free list is empty.
  431. TP6.0 Heapend
  432. ÚÄÄÄÄÄÄÄÄÄ¿ <ÄÄÄÄ
  433. ³ ³
  434. ³ ³
  435. ³ ³
  436. ³ ³
  437. ³ ³
  438. ³ ³
  439. ³ ³
  440. ³ ³ HeapPtr
  441. ÚÄ>ÃÄÄÄÄÄÄÄÄÄ´ <ÄÄÄÄ
  442. ³ ³ ³
  443. ³ ÃÄÄÄÄÄÄÄÄÄ´
  444. ÀÄij Free ³
  445. ÚÄ>ÃÄÄÄÄÄÄÄÄÄ´
  446. ³ ³ ³
  447. ³ ÃÄÄÄÄÄÄÄÄÄ´
  448. ÀÄij Free ³ FreeList
  449. ÃÄÄÄÄÄÄÄÄÄ´ <ÄÄÄÄ
  450. ³ ³ Heaporg
  451. ÃÄÄÄÄÄÄÄÄÄ´ <ÄÄÄÄ
  452. }