(**********************************************************************

    :Program.    Rows.def
    :Contents.   generic data type: variable length arrays
    :Author.     Nicolas Benezan [bne]
    :Address.    Postwiesenstr. 2, D7000 Stuttgart 60
    :Phone.      711/333679
    :Copyright.  Public Domain
    :Language.   Modula-2
    :Translator. M2Amiga AMSoft V3.11
    :Imports.    TaskMemory [bne]
    :History.    V1.0e [bne] 12.Jan.1989
    :Update.     allocation procedures added [bne] 19.Jan.1989

**********************************************************************)

DEFINITION MODULE Rows;

FROM SYSTEM     IMPORT ADDRESS,BYTE;

TYPE    Row;

VAR     RowsAllocProc:PROCEDURE(VAR ADDRESS,LONGINT);
        RowsDeallocProc:PROCEDURE(VAR ADDRESS);
(* defaults are TaskMemory.Allocate, TaskMemory.Deallocate *)

PROCEDURE Dim(VAR row:Row;NumElements:LONGINT;
              SizeOfElements:CARDINAL):BOOLEAN;
(*:Input.       NumElements: number of elements in the new Row
  :Input.       SizeOfElements: size in bytes of the Row's elements
  :Output.      row: new initialised Row
  :Result.      TRUE if there was enough free memory for the Row
  :Note.        If the result is FALSE the row is still not initialized
  :Semantic.    Initializes a Row and fills all elements with zero
  :Note.        DO NOT perform any operation on unititialized Rows !
  :Note.        before you Re-Dim() a Row you MUST Discard() it !
*)
PROCEDURE Discard(VAR row:Row);
(*:Input.       row: any Row previously initialised
  :Semantic.    Frees all memory consumed by the row
  :Note.        DO NOT perform any operation on Disscard()ed Rows
  :Note.        (except Dim(), of course) !
*)
PROCEDURE Read(row:Row;Index:LONGINT;VAR Data:ARRAY OF BYTE);
(*:Input.       row: the Row Read() should refer to
  :Input.       Index: number of the Element you want to Read()
  :Note.        Index must be inside [0..NumElements-1]
  :Output.      Data: variable where the element will be copied to
*)
PROCEDURE Write(row:Row;Index:LONGINT;Data:ARRAY OF BYTE);
(*:Input.       row: the Row Write() should refer to
  :Input.       Index: number of the Element you want to Write()
  :Note.        Index must be inside [0..NumElements-1]
  :Input.       Data: data that will be copied to the element
*)
PROCEDURE Assign(Source:Row;VAR Destination:Row):BOOLEAN;
(*:Input.       Source: The (properly Dim()ed) Row you want to copy
  :Input.       Destination: Row of the same NumElements+SizeOfElements
  :Input.       Destination: or a Row that hasn't been Dim()ed yet
  :Output.      Destination: copy of the Source, undefined if Result=FALSE
  :Note.        if Destination wasn't Dim()ed it is Dim()ed automaticaly
  :Result.      FALSE if an error occured, otherwise TRUE
  :Semantic.    performs an assignment by copying all data
  :Note.        row2:=row1 doesn't really copy
*)
(*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*)
(* the following is useful if you have Rows as "open array parameters"*)
(*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*)
PROCEDURE High(row:Row):LONGINT;
(*:Input.       row: any Row of which you don't know NumElements
  :Result.      highest possible Index for the row
  :Result.      if the Row is not Dim()ed High() may be undefined
  :Semantic.    High() is for Rows what HIGH() is for ARRAYs
*)
PROCEDURE CompSize(row:Row):CARDINAL;
(*:Input.       row: any Row you want to know the SizeOfElements
  :Result.      Size of the Row's Elements in bytes
  :Result.      if the Row is not Dim()ed CompSize() may be undefined
*)

(*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*)
(* WARNING: Use the following procedures carefully !                    *)
(*нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн*)
PROCEDURE Export(row:Row;VAR Base:ADDRESS;VAR Size:LONGINT);
(*:Input.       row: any (properly Dim()ed !) Row
  :Output.      Base: the row's data base address in memory
  :Output.      Size: the row's data size in bytes
  :Semantic.    Returns the address and size of the row's data buffer
  :Note.        You can use this if you want to Write() a Row to a File
  :Note.        but don't make any assumptions of how to interpret the data
  :Note.        Don't use Export() on Import()ed rows
  :Note.        (in this case the buffer is known anyway)
*)
PROCEDURE Import(VAR row:Row;NumElements:LONGINT;
              SizeOfElements:CARDINAL;Base:ADDRESS;Size:LONGINT);
(*:Input.       row: empty Row (created by Dim(row,0,0) )
  :Input.       NumElements: how many elements are in the buffer
  :Input.       SizeOfElements: length of each element in bytes
  :Input.       Base: the buffer base address in memory
  :Input.       Size: the buffer size in bytes
  :Output.      row: Row that contains the buffer's data
  :Semantic.    creates a Row out of a buffer with a given Base and Size
  :Note.        You can use this to Read() a Row from a file
  :Note.        DO NOT re-use the buffer until Discard(row),
  :Note.        data is not copied ! Neither does Import() allocate a new
  :Note.        buffer nor will Discard() deallocate the buffer if the
  :Note.        row was an Import()ed one !
  :Note.        WARNING: if the buffer doesn't fit the specified NumElements
  :Note.        and SizeOfElements the result is undefined !
*)
END Rows.
