|
|
|
|
||
|
DEFINITION MODULE DataTables; (******************************************************************* Module DataTables (Version 1.0) Copyright (c) 1997-2006 by Dimitrios Gyalistras, Andreas Fischlin and ETH Zurich. Purpose Handles data tables. Remarks A data table consists of a header and a rectangular data field. The header is used to identify the individual columns of the data field. All data within one column must contain data of one and the same type. Any combinations of different types of columns are possible. Programming o Design Dimitrios Gyalistras 16/01/1997 Andreas Fischlin 16/01/1997 o Implementation Dimitrios Gyalistras 16/01/1997 Andreas Fischlin 16/01/1997 ETH Zurich Systems Ecology CHN E 35.1 Universitaetstrasse 16 8092 Zurich SWITZERLAND URLs: <mailto:RAMSES@env.ethz.ch> <http://www.sysecol.ethz.ch> <http://www.sysecol.ethz.ch/SimSoftware/RAMSES> Last revision of definition: 09/08/1997 AF *******************************************************************) FROM SYSTEM IMPORT ADDRESS; FROM DMStrings IMPORT String; FROM DMFiles IMPORT TextFile; FROM DMLanguage IMPORT onlyAnInsert; CONST notDone = onlyAnInsert; (* All procedures exported below return resCode = DMLanguage.allOk if the call to the procedure was succesfull, else resCode = notDone. *) TYPE DataTable; (* Data tables are matrix like objects consisting of rows and colums. In contrast to the well known matrices consisting of numbers, data tables may consist of elements of different types (see DTElementType), however, within a single column types should be the same. Missing values are tolerated (symbol NA - not available). Implementation restriction: Memory for data tables will be allocated efficiently, i.e. only to the size actually required. Columns are numbered from 1 to 256 and rows from 1 to 3072. *) CONST unknownRowNr = 0; (* rows start at 1 *) unknownColNr = 0; (* columns start at 1 *) VAR notExistingDataTable: DataTable; (* read only *) (*****************************************************************************) TYPE String63 = ARRAY [0..63] OF CHAR; DTElementType = ( unknownDTEle, integer, longint, real, longreal, boolean, ident, string ); DTColDescr = RECORD type : DTElementType; id : String63; END; DTElementPtr = POINTER TO DTElement; SHORTENUM = CHAR; (* will hold [CHAR(MIN(DTElementType))..CHAR(MAX(DTElementType))] *) DTElement = RECORD def: BOOLEAN; (* def holds whether DTElement is defined *) type: SHORTENUM; (* type holds the type *) CASE : DTElementType OF | unknownDTEle : undefval : ARRAY [0..(SIZE(LONGREAL) DIV SIZE(CHAR))-1] OF CHAR; | real : real : REAL; | longreal : lreal : LONGREAL; | integer : int : INTEGER; | longint : lint : LONGINT; | boolean : boo : BOOLEAN; | ident : id : String; | string : str : String; END;(*CASE*) END; (* assumptions made: (i) SIZE(CHAR) = 1 (ii) SIZE(BOOLEAN) <= SIZE(INTEGER) (iii) SIZE(INTEGER) <= SIZE(LONGINT) (iv) SIZE(REAL) <= SIZE(LONGREAL) (v) SIZE(ORD(MAX(DTElementType))) <= SIZE(CHAR) (vi) SIZE(LONGREAL) = SIZE(undefval) (* implies assumption (i) *) (vii) SIZE(undefval) >= SIZE(of all types) Assumptions (v) to (vii) are tested during module initialization. The latter are assumed to be satisfied by all compilers. *) PROCEDURE ShortDTEType(t: DTElementType): SHORTENUM; PROCEDURE DTEType(t: SHORTENUM): DTElementType; (*****************************************************************************) (* Object management *) (*****************************************************************************) PROCEDURE GetDTElementTypeDescr( dt: DTElementType; VAR descr: ARRAY OF CHAR ); (*--------------------------------------------------------------------------*) PROCEDURE DeclDataTable( tableName : ARRAY OF CHAR; nRows : INTEGER; nCols : INTEGER; VAR colDescr : ARRAY OF DTColDescr; (* VAR for speed-up only *) VAR dt : DataTable; VAR resCode : INTEGER; VAR insert : ARRAY OF CHAR ); PROCEDURE RemoveDataTable( VAR dt : DataTable ); PROCEDURE DataTableExists( dt : DataTable ): BOOLEAN; (*--------------------------------------------------------------------------*) PROCEDURE FirstDataTable():DataTable; PROCEDURE NextDataTable( dt: DataTable ):DataTable; (*--------------------------------------------------------------------------*) PROCEDURE GetDataTableAttr( dt : DataTable; VAR attr : ADDRESS; VAR resCode : INTEGER; VAR insert : ARRAY OF CHAR ); PROCEDURE SetDataTableAttr( dt : DataTable; attr : ADDRESS; VAR resCode : INTEGER; VAR insert : ARRAY OF CHAR ); (*--------------------------------------------------------------------------*) PROCEDURE LockDataTable( dt : DataTable; VAR resCode : INTEGER; VAR insert : ARRAY OF CHAR ); (* content of data table dt can no longer be modified. Data table dt can only be discarded as a whole. *) PROCEDURE UnlockDataTable( dt : DataTable; VAR resCode : INTEGER; VAR insert : ARRAY OF CHAR ); PROCEDURE IsDataTableLocked( dt : DataTable ): BOOLEAN; (*--------------------------------------------------------------------------*) PROCEDURE GetDataTableName( dt : DataTable; VAR tableName : ARRAY OF CHAR; VAR resCode : INTEGER; VAR insert : ARRAY OF CHAR ); PROCEDURE GetDataTableDescr( dt : DataTable; VAR tableName : ARRAY OF CHAR; VAR nRows : INTEGER; VAR nCols : INTEGER; VAR colDescr : ARRAY OF DTColDescr; VAR resCode : INTEGER; VAR insert : ARRAY OF CHAR ); PROCEDURE GetDataTableColDescr( dt : DataTable; colNo : INTEGER; VAR colDescr : DTColDescr; VAR resCode : INTEGER; VAR insert : ARRAY OF CHAR ); PROCEDURE SetDataTableDescr( dt : DataTable; tableName : ARRAY OF CHAR; VAR colDescr : ARRAY OF DTColDescr; (* VAR for speed-up only *) VAR resCode : INTEGER; VAR insert : ARRAY OF CHAR ); PROCEDURE GetDataTableDim( dt : DataTable; VAR nRows : INTEGER; VAR nCols : INTEGER; VAR resCode : INTEGER; VAR insert : ARRAY OF CHAR ); (*--------------------------------------------------------------------------*) VAR emptyDataEle: DTElement; (* read only *) (* Inite your variables of type DTElement with emptyDataEle. Strongly recommended prior to any further use! *) PROCEDURE ClearDTEle( eleType: DTElementType; VAR ele: DTElement ); (* Sets ele to emptyDataEle; NOTE: It deallocates also strings, if eleType requires this. Thus, precondition for ele is either ele = emptyDataEle or a valid value of type eleType from previous use. *) PROCEDURE CopyDTEle( eleType: DTElementType; VAR from : DTElement; (* VAR for speed-up only *) VAR to : DTElement ); (* to has to satisfy the same preconditions as required by ClearDTEle *) (* NOTE: for efficiency the following procedures do not check the validity of the input parameters!! *) PROCEDURE GetDTEle( dt : DataTable; row, col : INTEGER; VAR ele : DTElement ); (* ele has to satisfy the same preconditions as required by ClearDTEle *) PROCEDURE SetDTEle( VAR ele : DTElement; (* VAR for speed-up only *) dt : DataTable; row, col : INTEGER ); (* ele has to satisfy the same preconditions as required by ClearDTEle plus that dt contains already well defined types for all colums. *) PROCEDURE DTEleADR( dt : DataTable; row, col : INTEGER): DTElementPtr; (* NOTE: This routine is a loophole circumventing the locking mechanism entirely, so use it with caution and for reading ONLY, unless the dt is not locked!!! *) (*****************************************************************************) (* Reading of DataTables from file *) (*****************************************************************************) PROCEDURE SetMisValParams( misValStr, misQuotStr : ARRAY OF CHAR; misReal : REAL; misInt : INTEGER; misLReal : LONGREAL; misLInt : LONGINT; misBool : BOOLEAN; VAR resCode : INTEGER; VAR insert : ARRAY OF CHAR ); PROCEDURE GetMisValParams( VAR misValStr, misQuotStr: ARRAY OF CHAR; VAR misReal : REAL; VAR misInt : INTEGER; VAR misLReal : LONGREAL; VAR misLInt : LONGINT; VAR misBool : BOOLEAN); (* The values misReal and misInt are returned if the string "misValStr" is encountered at the place of a real (or longreal), or an integer (or longint), respectively. The default settings are: misValStr = 'NA' misQuotStr = '???' misReal = DMConversions.UndefREAL(); misInt = MIN(INTEGER)+1; misLReal = DMConversions.UndefLONGREAL(); misLInt = MIN(LONGINT)+1; misBool = BOOLEAN(ORD(MAX(BOOLEAN))+1); *) PROCEDURE ReadDataTable( inFName : ARRAY OF CHAR; tryOpenFile : BOOLEAN; keepFileOpen : BOOLEAN; eolSeparated : BOOLEAN; tableName : ARRAY OF CHAR; VAR dt : DataTable; VAR resCode : INTEGER; VAR insert : ARRAY OF CHAR ); (* Reads DataTable dt from file inFName. If tryOpenFile=FALSE the file must have already been opened for scanning by means of procedure Scanner.InitFileScan. If the file is kept open, the Scanner procedures can be used to continue reading, e.g. to read a further table. The expected syntax is: DataTable = TableHeader TableLine {TableLine} "END". TableHeader = IDENTIFIER {IDENTIFIER} lineSeparator. TableLine = TableEle {TableEle} lineSeparator. TableEle = (INTEGER | LONGINT | REAL | LONGREAL | IDENTIFIER | STRING | BOOLEAN ). If eolSeparated=TRUE then lineSeparator = "EOL". and all elements of TableHeader or a TableLine are expected on one line. Otherwise lineSeparator = ";". In this case the elements of TableHeader or a TableLine can be distributed over any number of lines. The elementary data types are (given in regular expression notation): INTEGER = [+-]?[0-9]+ LONGINT = [+-]?[0-9]+ "D" REAL = [+-]?[0-9]+ "." [0-9]+ (("E"|"e")[+-]?[0-9]+)? LONGREAL = [+-]?[0-9]+ "." [0-9]+ (("D"|"d")[+-]?[0-9]+)? IDENTIFIER = [a-zA-Z]+ [_a-zA-Z0-9]* STRING = ('.*')|(".*") BOOLEAN = "TRUE" | "FALSE" Comments start with "(*" and close with "*)". Recursive comments are possible. *) PROCEDURE GetColDescriptors( VAR fName : ARRAY OF CHAR; (* VAR for speed-up only *) eolSeparated : BOOLEAN; VAR nCols : INTEGER; VAR colDescr : ARRAY OF DTColDescr; VAR resCode : INTEGER; VAR insert : ARRAY OF CHAR ); (* Retrieves header line (column descriptors) by reading from current position in a file previously opened by means of procedure Scanner.InitFileScan. *) PROCEDURE GetNextDataRow( VAR fName : ARRAY OF CHAR; (* VAR for speed-up only *) eolSeparated : BOOLEAN; nCols : INTEGER; VAR colDescr : ARRAY OF DTColDescr; (* is also set! *) VAR rowData : ARRAY OF DTElement; VAR endOfData : BOOLEAN; VAR resCode : INTEGER; VAR insert : ARRAY OF CHAR ); (* Retrieves a table row by reading from current position in a file previously opened by means of procedure Scanner.InitFileScan. If for the column descriptor of the i-th column holds colDescr[i].type= unknownDTEle then the type will be set according to the type of data found for column i (unless a missing value occurs). endOfData returns TRUE if the end of the data table has been reached (keyword "END"). rowData must be properly initialized all with emptyDataEle, when calling GetNextDataRow the first time. *) (*****************************************************************************) (* Writing of DataTables to file *) (*****************************************************************************) PROCEDURE SetNumOutputParams( nIntChars : INTEGER; nLIntChars : INTEGER; nRealChars : INTEGER; nDecDigits : INTEGER; nLRealChars : INTEGER; nLRDecDigits : INTEGER); PROCEDURE GetNumOutputParams( VAR nIntChars : INTEGER; VAR nLIntChars : INTEGER; VAR nRealChars : INTEGER; VAR nDecDigits : INTEGER; VAR nLRealChars : INTEGER; VAR nLRDecDigits : INTEGER ); PROCEDURE WriteDataTable( outF : TextFile; eolSeparated : BOOLEAN; indentStr : ARRAY OF CHAR; lastIndentStr : ARRAY OF CHAR; VAR dt : DataTable; VAR resCode : INTEGER; VAR insert : ARRAY OF CHAR ); (* Dumps DataTable dt to file outF. The file must have already been opened for writing by means of a DMFiles procedure. If eolSeparated=FALSE data lines will be separated by ";". Each new line written starts with indentStr, the last line containing the keyword "END" with lastIndentStr. *) END DataTables.
|
||
|
|
|