farAlloc v. 1.00 ---------------- (C) 1993 Jussi Lahdenniemi a.k.a. Avatar the Abnormal / The Square The problem ----------- Turbo/Borland Pascal supports only arrays and memory allocations up to 64 kilobytes. Sometimes that just is not enough. Probably you have also run into this problem several times, but have had to split the array/memory block into two or more smaller ones. They are not very easy to handle since you must check first in which block the offset you would like to refer is in. Also, blockReading to those arrays is quite complicated. The solution ------------ FarAlloc is the solution to that problem. It gives you the tools needed to allocate memory up to the heap size - a 400- kilobyte array is not impossible to handle anymore! And all that memory farAlloc allocates is continous - just like an ordinary array! FarAlloc defines a new type, farArray, which is an object. If you are not friendly with objects, don't stop reading now! FarAlloc is very easy to use. Installation ------------ In the packet there are two TPUs; one for TP 6.0 and one for BP/TP 7.0. The TPU for TP6 is FARALLOC.T60 and the one for TP/BP7 is FARALLOC.T70. You have to rename the correct unit to FARALLOC.TPU. With that, the farAlloc is installed. Licences/Anything like that --------------------------- Using the farAlloc is fully FREE! You have to pay nothing to me; anyway, I would appreciate a letter or just a postcard from you if you like this unit. Also, give me some credits in your program's start/end texts.. That's not much asked for such a wonderful unit, is it? Using the farAlloc ------------------ Using the farAlloc is quite straightforward. Just add the farAlloc into the uses-statement in the beginning of your program. Then you have to define a variable of type PfarArray. Initializing the farArray is done like this: Var myArray : PfarArray; { define the variable } ... myArray:=new(PfarArray,init(200000,true)); This initializes the variable myArray and allocates 200000 bytes of memory for it. The 'true' means that range checking for this array will be on - 'false' would turn it off speeding the program execution up slightly. If the range checking is on, an attempt to refer indexes outside the array triggers the runtime error 201 (range check error). Now that you have intialized your array, you would maybe like to use the memory you have just allocated. There are many ways to do it. The easiest method to write and read data is to use the methods I have defined in the PfarArray. They are rB, rW, rL, rP, rC, wB, wW, wL, wP and wC. The first letter in the method name indicates 'read' or 'write', and the last letter is the type; byte, word, longint, pointer or char. So, if you would like to read a char type data from the index 120000 in the array, do it like this: writeln(myArray.rC(120000)); Writing the new value to the array is as easy as reading the value : myArray.wL(120000,12345678); writes a longint, 12345678, into the array to index 120000. Defining your own types, you would certainly like to read the variables of your own type as easily as the already-defined types. Writing the r* and w* methods is quite easy. Here is an example: Type myRecord = Record name : String[30]; address : String[30]; age : Longint; { For aged people.. ;-) } dead : Boolean; End; PmyFarArray = ^TmyFarArray; TmyFarArray = Object(TfarArray) Procedure rMYREC(offs:longint;var data:myRecord); { ^^^^^^^^^^^^^^^^^ Since a record can not be returned by a function } Procedure wMYREC(offs:longint;data:myRecord); end; ... Procedure TmyFarArray.rMYREC; { declare the methods } begin if rangeCheck then rngc(offs+sizeOf(myRecord));{ Range checking } Move(self^.addr(offs)^,data,sizeOf(myRecord)); { self is there for } { just to be sure } { that addr is not } { mixed with the } { Pascal's own addr } { function } end; Procedure TmyFarArray.wMYREC; begin if rangeCheck then rngc(offs+sizeOf(myRecord)); Move(data,self.addr(offs)^,sizeOf(myRecord)); end; ... Var myArray:PmyFarArray; myFriend:myRecord; ... myArray:=new(PmyFarArray,init... ... myArray^.wMyRec(1000,myArray); ... myArray^.rMyRec(1000,myArray); ... ... That wasn't too complicated, was it? OOP is just a GREAT thing to have! BTW: I have defined also the w* methods as functions; they return the same value that is given to them. It may be a good thing in some if:s and things like that.. Here's an example: Instead of writing: myArray^.wL(1000,myLong); if L>10000 then overTenThousand; you can write if myArray^.wL(1000,myLong)>10000 then overTenThousand; I don't know if that makes any sense, but it does not bother anybody.. Just turn the extended syntax on ({$X+} or Options|Compiler|Extended syntax) and you don't have to care about the returned value. You can just write myArray.wL(1000,myLong) and the longint it returns will be discarded. After using the array, it might be wise to release the memory it allocates. Releasing the memory is done with the destructor done like this: dispose(myArray,done); This releases the memory myArray is using. For now, you should be able to handle the arrays properly. Using the farAlloc unit, you can also use the standard GetMem/FreeMem/New/Dispose/Mark/Release functions of Pascal. The farArrays are fully compatible with them. BTW: TfarArray.loc holds the starting pointer of the array! Oh yes, maybe you would like to load something into your arrays, too! I have not (yet) defined the new blockRead/blockWrite functions for the farArrays, so you can only read up to 64k of data at a time. If your array is 100000 bytes, you have to load it full in two parts. Anyway, that is easy: Just blockRead(myFile,myArray^.loc^,50000); { the first part } blockRead(myFile,myArray^.addr(50000)^,50000); { the rest } NOW you should know everything about handling these farArrays. I'll paste the type definition straight from the farAlloc.PAS here: Type PfarArray = ^TfarArray; TfarArray = Object {$IFDEF VER70} private {$ENDIF} size : Longint; { Private - you don't see } { these in TP 7.0+ } Function allocateMemory:Boolean; Procedure rngc(offs:Longint); {$IFDEF VER70} public {$ENDIF} loc : Pointer; { Array location in memory } rangeCheck : Boolean; Constructor init(blkSize:longint;doRC:boolean); { initialize } Function rB(offs:longint):byte; virtual; { read byte } Function rW(offs:longint):word; virtual; { read word } Function rL(offs:longint):longint; virtual; { read longint } Function rC(offs:longint):char; virtual; { read char } Function rP(offs:longint):pointer; virtual; { read pointer } Function addr(offs:longint):pointer; virtual; { returns a pointer } { to the specified } { index } Function wB(offs:longint;n:byte):byte; virtual; { write byte } Function wW(offs:longint;n:word):word; virtual; { write word } Function wL(offs:longint;n:longint):longint; virtual; { write longint } Function wC(offs:longint;n:char):char; virtual; { write char } Function wP(offs:longint;n:pointer):pointer; virtual; { write pointer } Destructor done; { deinitialize } end; There you should have all the info needed in succesfull programming with the farArrays. Oh yes - with BP7.0, you can't use the protected mode nor Windows as the target environment with the farAlloc. Just the real mode is allowed. Expansions for the protected mode are coming as I have time to take a closer look to those 'selectors' and all the stuff like that in the protected mode and figure out how they are handled. Addresses --------- You can write to me by mail to the address Jussi Lahdenniemi Rautia SF-36420 Sahalahti Finland or send me FidoNet netmail into my point: 2:222/352.20 By Internet the mail to me can be sent via the FidoNet<->Internet gateway, and the address is then jussi.lahdenniemi@p20.f352.n222.z2.fidonet.org BE SEEING YOU!