| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724 |
- IMPLEMENTATION MODULE NdxBones;
- (*
- * REPERTOIRE
- * Release 1.6
- * By Charles Bradford and Cole Brecheen
- * (c) Copyright 1985-1992 PMI
- * Green Bay, Wisconsin
- * All rights reserved
- * (414) 468-6040
- *
- * $Header: D:/logfiles/mods/ndxbones.mov 1.7 10 Mar 1991 15:30:02 coleb $
- *
- *)
- (*EntryDiag:
- IMPORT Diagnostics;
- :EntryDiag*)
- IMPORT ErrorNames;
- IMPORT HandleIO;
- IMPORT GenLists;
- IMPORT ListUtils;
- IMPORT LowLevel;
- IMPORT M2Strings;
- IMPORT NdxTypes;
- IMPORT Numbers;
- IMPORT NumTypes;
- IMPORT PosUtils;
- IMPORT StrEdit;
- IMPORT StringIO;
- IMPORT SYSTEM;
- IMPORT VStorage;
- VAR
- Initialized : BOOLEAN;
- CONST
- StartChar = 'B';
- EndChar = 'E';
- EncodedChar = 'R';
- NdxMarkChar = 'X';
- (*This character marks the start of the ndx list. We use it
- to make sure we've got the right file offset when we back
- up and read the list.*)
- blank = ' ';
- null = '';
- AfterLastElmt = 65535;
- PROCEDURE BiggestRecord( NdxFile: NdxTypes.NdxFileType ): CARDINAL;
- VAR
- TmpElmt: NdxTypes.NdxElement;
- TypeCode, LstLngth, TmpResult: CARDINAL;
- BEGIN
- IF GenLists.ListLength( NdxFile^.Ndx ) = 0 THEN
- RETURN 0;
- END;
- GenLists.GetElmt( NdxFile^.Ndx, 1, TmpElmt, TypeCode );
- TmpResult := TmpElmt.UsedChars;
- LstLngth := GenLists.ListLength( NdxFile^.Ndx );
- WHILE GenLists.ElmtNow( NdxFile^.Ndx ) < LstLngth DO
- GenLists.NextElmt( NdxFile^.Ndx, 1, TmpElmt, TypeCode );
- IF TmpElmt.UsedChars > TmpResult THEN
- TmpResult := TmpElmt.UsedChars;
- END;
- END;
- RETURN TmpResult;
- END BiggestRecord;
- PROCEDURE FindRecord( NdxFile: NdxTypes.NdxFileType; VAR
- RecordName : ARRAY OF CHAR; VAR offset : LONGINT; VAR
- UsedRecSize, AllocSize: CARDINAL) : BOOLEAN;
- (* Move in the record list to this record. If can't find
- record, AllocSize is set to the collating position where
- record requested would be inserted. All other VAR results
- are meaningless *)
- VAR
- found, StillLooking: BOOLEAN;
- HiBound, LoBound, distance, ListPos, TypeCode: CARDINAL;
- CompResult: INTEGER;
- TmpElmt : NdxTypes.NdxElement;
- PROCEDURE AtCurrentPtr( VAR InsertionPoint: CARDINAL ): BOOLEAN;
- (*Because lots of routines call FindRecord, sometimes
- in sequence when they're all looking for the same record,
- it's usually a good bet that the record you want is
- either at the current pointer for the ndx list or at
- least needs to be inserted there. This routine
- determines whether that is true, and if it is, allows us
- to skip the binary search through the whole list.*)
- VAR
- CompResult: INTEGER;
- now: CARDINAL;
- BEGIN
- InsertionPoint := 0;
- (*If AtCurrentPtr comes back FALSE but with a non-zero
- value in its parameter, it means we didn't find the
- record but we know its insertion point.*)
- now := GenLists.ElmtNow(NdxFile^.Ndx);
- IF (now = 0) OR (now > GenLists.ListLength(NdxFile^.Ndx)) THEN
- (* list has not been used at all yet (or is empty) *)
- RETURN FALSE;
- END;
- GenLists.GetElmt( NdxFile^.Ndx, now, TmpElmt, TypeCode );
- CompResult := CompareProc(RecordName, TmpElmt.RecName);
- CASE CompResult OF
- 0 :
- M2Strings.Assign( TmpElmt.RecName, RecordName );
- RETURN TRUE;
- | 1 :
- IF GenLists.ElmtNow( NdxFile^.Ndx ) = 1 THEN
- (*We were at the first of the list and RecordName was
- less than TmpElmt.RecName, so we know the
- insertion point.*)
- InsertionPoint := 1;
- RETURN FALSE;
- END;
- GenLists.NextElmt( NdxFile^.Ndx, -1, TmpElmt, TypeCode );
- CompResult := CompareProc( RecordName, TmpElmt.RecName );
- IF CompResult = 0 THEN
- M2Strings.Assign( TmpElmt.RecName, RecordName );
- RETURN TRUE;
- ELSIF CompResult = -1 THEN
- (*We know the insertion point is between this
- element and the last one we tried.*)
- InsertionPoint := GenLists.ElmtNow(NdxFile^.Ndx) + 1;
- END;
- RETURN FALSE;
- |-1 :
- IF now = GenLists.ListLength(NdxFile^.Ndx) THEN
- (*We were at the end of the list and RecordName was
- greater than TmpElmt.RecName, so we know the insertion
- point.*)
- InsertionPoint := now + 1;
- RETURN FALSE;
- END;
- GenLists.NextElmt( NdxFile^.Ndx, 1, TmpElmt, TypeCode );
- CompResult := CompareProc( RecordName, TmpElmt.RecName );
- IF CompResult = 0 THEN
- M2Strings.Assign( TmpElmt.RecName, RecordName );
- RETURN TRUE;
- ELSIF CompResult = 1 THEN
- (*We know the insertion point is between this
- element and the last one we tried.*)
- InsertionPoint := GenLists.ElmtNow(NdxFile^.Ndx);
- END;
- RETURN FALSE;
- END;
- RETURN FALSE;
- END AtCurrentPtr;
- BEGIN
- IF AtCurrentPtr( AllocSize ) THEN
- found := TRUE;
- ELSE
- IF AllocSize # 0 THEN
- RETURN FALSE;
- END;
- found := FALSE;
- offset := Numbers.Lc( 0);
- UsedRecSize := 0;
- ListPos := 1;
- HiBound := GenLists.ListLength(NdxFile^.Ndx) + 1;
- IF HiBound = 1 THEN
- AllocSize := 1;
- RETURN FALSE;
- END;
- LoBound := 0;
- StillLooking := TRUE;
- GenLists.GetElmt( NdxFile^.Ndx, 1, TmpElmt, TypeCode );
- END;
- WHILE (NOT found) AND StillLooking DO
- CompResult := CompareProc(RecordName,
- TmpElmt.RecName);
- IF CompResult = 0 THEN
- M2Strings.Assign( TmpElmt.RecName, RecordName );
- found := TRUE;
- ELSIF CompResult < 0 THEN
- (* new name is higher than current spot in list;
- so try to move higher in list *)
- distance := (HiBound - ListPos) DIV 2;
- LoBound := ListPos;
- INC( ListPos, distance );
- IF distance = 0 THEN
- StillLooking := FALSE;
- AllocSize := ListPos + 1;
- ELSE
- GenLists.NextElmt(NdxFile^.Ndx, distance, TmpElmt, TypeCode);
- END;
- ELSE
- distance := (ListPos - LoBound) DIV 2;
- HiBound := ListPos;
- DEC( ListPos, distance );
- IF distance = 0 THEN
- StillLooking := FALSE;
- AllocSize := ListPos;
- ELSE
- GenLists.NextElmt(NdxFile^.Ndx, -INTEGER(distance),
- TmpElmt, TypeCode);
- END;
- END;
- END;
- IF NOT found THEN
- (*If we can't find RecordName in the list ... *)
- RETURN FALSE;
- ELSE
- (*Return file location of record.*)
- offset := TmpElmt.FilePos;
- UsedRecSize := TmpElmt.UsedChars;
- AllocSize := TmpElmt.Allocated;
- RETURN TRUE;
- END;
- END FindRecord;
- PROCEDURE RemoveCodes( Source: SYSTEM.ADDRESS; VAR TheSize: CARDINAL);
- (* Removes all chars that follow CodeChars, and changes
- TheSize to reflect number of chars removed. *)
- VAR
- tmpsize, toskip : CARDINAL;
- badspot : SYSTEM.ADDRESS;
- tmpchar : CHAR;
- BEGIN
- tmpsize := TheSize;
- tmpchar := CodeChar;
- LOOP
- toskip := PosUtils.PatternScan( SYSTEM.ADR(tmpchar),
- 1, Source, tmpsize );
- IF toskip >= tmpsize THEN
- RETURN
- END;
- badspot := LowLevel.AddAddr( Source, toskip + 1 );
- DEC( tmpsize, toskip + 1);
- LowLevel.ShiftArrayLeft( badspot, tmpsize, 1 );
- Source := badspot;
- DEC( TheSize);
- END;
- END RemoveCodes;
- PROCEDURE StripList( VAR TheList: GenLists.GenList);
- (* Converts CodedStrs to CodeChars in TheList *)
- VAR
- OldSize, NewSize, ElmntType, cnt, leng: CARDINAL;
- SubList: GenLists.GenList;
- GenAddr: SYSTEM.ADDRESS;
- BEGIN
- leng := GenLists.ListLength( TheList );
- FOR cnt := 1 TO leng DO
- GenLists.GetElmtAdr( TheList, cnt, GenAddr, OldSize, ElmntType);
- NewSize := OldSize;
- IF ElmntType # GenLists.ListCode THEN
- RemoveCodes( GenAddr, NewSize );
- IF OldSize # NewSize THEN
- (* do not replace unless code chars found *)
- GenLists.ListReplaceAdr( GenAddr, NewSize, ElmntType,
- TheList, cnt);
- END;
- ELSE
- (* this element is a list *)
- GenLists.GetChildList( TheList, cnt, SubList);
- StripList( SubList );
- (* strip this sub list *)
- END;
- END;
- END StripList;
- PROCEDURE ReadStructure( NdxFile: NdxTypes.NdxFileType;
- VAR HadToRebuild: BOOLEAN): BOOLEAN;
- (*Note that this is the first procedure that will have an
- opportunity to determine whether the user is trying to open
- a file that is not a valid NdxFile. It has to be very
- careful about relying on values it gets from the file.*)
- VAR
- tmpstr: ARRAY [0..80] OF CHAR;
- checkchar: CHAR;
- bufsize, dumcard: CARDINAL;
- ReadBuf : SYSTEM.ADDRESS;
- TmpHandle: VStorage.MemHandle;
- BEGIN
- (*ReadStructure*)
- HadToRebuild := FALSE;
- bufsize := 0;
- HandleIO.SetFilePtr( NdxFile^.handle, HandleIO.FromStart, NumTypes.L0 );
- CASE HandleIO.BlockRead( NdxFile^.handle, SYSTEM.ADR(bufsize), 2) OF
- (*Read the file's first two bytes into bufsize.*)
- StringIO.NoError: (*fall through*);
- ELSE
- RETURN FALSE;
- END;
- HandleIO.SetFilePtr( NdxFile^.handle, HandleIO.FromStart, Numbers.Lc( 2));
- (*Put the pointer on the third byte in the file.*)
- IF NOT VStorage.IsAvailable( bufsize ) THEN
- ErrorNames.WarningName('Mem');
- RETURN FALSE;
- END;
- IF NOT VStorage.AllocMem( TmpHandle, bufsize ) THEN
- ErrorNames.WarningName('Mem');
- RETURN FALSE;
- END;
- ReadBuf := VStorage.LockMem( TmpHandle );
- CASE HandleIO.BlockRead( NdxFile^.handle, ReadBuf, bufsize) OF
- (*Read the structure record into the ReadBuf.*)
- StringIO.NoError, StringIO.EndOfFile: (*fall through*);
- ELSE
- VStorage.DeallocMem( TmpHandle, bufsize);
- RETURN FALSE;
- END;
- (*
- Diagnostics.diagBlock( NdxFile^.name, ReadBuf, bufsize );
- *)
- LowLevel.Fill( ReadBuf, 4, 0C );
- LowLevel.Fill( LowLevel.AddAddr(ReadBuf, bufsize - 2), 2, 0C );
- (*Wipe out the startsep and endsep that brackets the whole
- structure.*)
- VStorage.UnLockMem( TmpHandle );
- GenLists.NewList( NdxFile^.StructLst );
- ListUtils.HandleToList( TmpHandle, bufsize, StartSep, EndSep, 0, 0,
- NdxFile^.StructLst);
- IF GenLists.ListLength( NdxFile^.StructLst ) = 0 THEN
- GenLists.DisposeList( NdxFile^.StructLst);
- RETURN FALSE;
- END;
- GenLists.GetElmt( NdxFile^.StructLst, 1, tmpstr, dumcard);
- checkchar := tmpstr[0];
- M2Strings.Delete(tmpstr, 0, 1);
- IF NOT PosUtils.Equal( tmpstr, StructName) THEN
- GenLists.DisposeList( NdxFile^.StructLst);
- RETURN FALSE;
- ELSIF checkchar = IsGarbageByte THEN
- (*
- Diagnostics.diagS( 'STRUCTURE record is marked garbage', checkchar );
- *)
- RebuildProc( NdxFile );
- (*Structure record gets marked as garbage when you write a
- record but don't update the ndx. Gets marked okay when
- the ndx gets written.*)
- HadToRebuild := TRUE;
- END;
- GenLists.ListDelete( NdxFile^.StructLst, 1, 1);
- (* deletes the StructName from the Structure *)
- StripList( NdxFile^.StructLst );
- (*Removes CodedStrs from StructLst.*)
- RETURN TRUE;
- END ReadStructure;
- PROCEDURE MakeEmptyBuf( VAR StruList, BufList: GenLists.GenList);
- VAR
- LastCode, TheType, cnt, StructLstLength : CARDINAL;
- SubStruList, EmptyList: GenLists.GenList;
- BEGIN
- StructLstLength := GenLists.ListLength( StruList);
- LastCode := GenLists.ListCode;
- FOR cnt := 1 TO StructLstLength DO
- (* write a ListBuf element for each structure element *)
- TheType := ListUtils.TypeCheck( StruList, cnt );
- (* get next element from structure list *)
- IF TheType = GenLists.ListCode THEN
- IF LastCode = GenLists.ListCode THEN
- ErrorNames.WarningName( 'BadStruc' );
- END;
- GenLists.NewList( EmptyList);
- GenLists.ListInsert( EmptyList, GenLists.ListCode,
- BufList, AfterLastElmt);
- GenLists.GetChildList( StruList, cnt, SubStruList);
- MakeEmptyBuf( SubStruList, EmptyList);
- ELSE
- IF LastCode # GenLists.ListCode THEN
- GenLists.ListInsert( 0C, GenLists.StrCode, BufList,
- AfterLastElmt);
- END;
- END;
- LastCode := TheType;
- END;
- IF LastCode # GenLists.ListCode THEN
- GenLists.ListInsert( 0C, GenLists.StrCode, BufList,
- AfterLastElmt);
- END;
- END MakeEmptyBuf;
- PROCEDURE OpenNdxFile( VAR NdxFile: NdxTypes.NdxFileType;
- FileName: ARRAY OF CHAR): BOOLEAN;
- (*Uses HandleIO FindFile routine to open NdxFile. Returns
- FALSE if not found. Otherwise initializes NdxFile and
- creates linked list of record names, record sizes, and file
- offsets from the ndx stored at the end of NdxFile.*)
- PROCEDURE ReadNdx( NdxFile: NdxTypes.NdxFileType );
- VAR
- TmpAvail, len1, len2, FilePos, BytesToRead : LONGINT;
- CheckStr: ARRAY [0..1] OF CHAR;
- NdxAddr : SYSTEM.ADDRESS;
- TmpHandle : VStorage.MemHandle;
- TmpNdx: GenLists.GenList;
- ThisChunk: CARDINAL;
- BEGIN
- (*ReadNdx*)
- HandleIO.SetFilePtr(NdxFile^.handle, HandleIO.FromEnd,
- Numbers.Li( -4) );
- (*Goto end of file and read Ndx offset*)
- IF StringIO.NoError <> HandleIO.BlockRead(NdxFile^.handle,
- SYSTEM.ADR(FilePos), 4) THEN
- ErrorNames.WarningName( 'FRead' );
- RETURN;
- END;
- IF (FilePos < NumTypes.L0) OR
- ( FilePos > HandleIO.FileLength(NdxFile^.handle)) THEN
- (*
- Diagnostics.diagL( 'FilePos', FilePos );
- *)
- RebuildProc( NdxFile );
- RETURN;
- END;
- HandleIO.SetFilePtr(NdxFile^.handle, HandleIO.FromStart, FilePos);
- (*Now we should be sitting on the NdxMarker.*)
- NdxFile^.NdxFilePtr := FilePos;
- (*Set file pointer to start of the index.*)
- len1 := HandleIO.FileLength(NdxFile^.handle) - FilePos;
- (* len1 is the file size minus the data *)
- BytesToRead := len1 - Numbers.Lc( 6);
- (* the index size *)
- IF BytesToRead = NumTypes.L0 THEN
- (* return empty index if index area of file is empty *)
- GenLists.NewList( NdxFile^.Ndx );
- RETURN;
- END;
- (*Now we check to make sure our offset numbers are valid by
- looking for the NdxMarker.*)
- IF HandleIO.BlockRead(NdxFile^.handle, SYSTEM.ADR(CheckStr),
- 2) # StringIO.NoError THEN
- (*
- Diagnostics.diagL( 'BlockRead failure at', FilePos );
- *)
- RebuildProc( NdxFile );
- RETURN;
- END;
- IF NOT PosUtils.Equal( CheckStr, NdxMarker) THEN
- (*
- Diagnostics.diagS( 'Invalid CheckStr:', CheckStr );
- *)
- RebuildProc( NdxFile );
- RETURN;
- END;
- IF (BytesToRead MOD Numbers.Lc( SYSTEM.TSIZE(NdxTypes.NdxElement)))
- # NumTypes.L0 THEN
- (*If the size of the index does not divide evenly by the
- size of an NdxElement, then the size of an NdxElement
- has been changed since the file was last used, and we
- have to rebuild.*)
- (*
- Diagnostics.diagL( 'BytesToRead', BytesToRead );
- *)
- RebuildProc( NdxFile );
- RETURN;
- END;
- (* Next, read in the index *)
- GenLists.NewList( NdxFile^.Ndx );
- WHILE BytesToRead > NumTypes.L0 DO
- TmpAvail := VStorage.AvailMem();
- (*If EMS is installed, more than 64K may be available,
- so we do this in two steps.*)
- IF TmpAvail > NumTypes.L65535 THEN
- ThisChunk := 65535;
- ELSE
- ThisChunk := Numbers.C( TmpAvail );
- END;
- DEC( ThisChunk, ThisChunk MOD SYSTEM.TSIZE(NdxTypes.NdxElement) );
- IF ThisChunk < SYSTEM.TSIZE(NdxTypes.NdxElement) THEN
- ErrorNames.WarningName('Mem');
- RETURN;
- END;
- IF BytesToRead > Numbers.Lc( ThisChunk) THEN
- BytesToRead := BytesToRead - Numbers.Lc( ThisChunk );
- ELSE
- ThisChunk := Numbers.C( BytesToRead);
- BytesToRead := NumTypes.L0;
- END;
- IF NOT VStorage.AllocMem( TmpHandle, ThisChunk ) THEN
- ErrorNames.WarningName('Mem');
- RETURN;
- END;
- NdxAddr := VStorage.LockMem( TmpHandle );
- IF HandleIO.BlockRead(NdxFile^.handle, NdxAddr, ThisChunk)
- # StringIO.NoError THEN
- VStorage.UnLockMem( TmpHandle );
- VStorage.DeallocMem( TmpHandle, ThisChunk );
- (*
- Diagnostics.diagC( 'Unable to read ThisChunk # of bytes:', ThisChunk );
- *)
- RebuildProc( NdxFile );
- RETURN;
- END;
- VStorage.UnLockMem( TmpHandle );
- GenLists.NewList( TmpNdx );
- ListUtils.HandleToList( TmpHandle, ThisChunk, '', '',
- SYSTEM.TSIZE(NdxTypes.NdxElement), NdxTypes.NdxTypeCode,
- TmpNdx );
- (*The nulls mean "there are no delimiters in the
- block."*)
- len1 := Numbers.Lc( GenLists.ListLength(TmpNdx));
- len2 := Numbers.Lc( GenLists.ListLength(NdxFile^.Ndx));
- IF (len1 + len2) > NumTypes.L65535 THEN
- ErrorNames.WarningName('RecLim');
- END;
- GenLists.JoinLists( TmpNdx, NdxFile^.Ndx,
- GenLists.ListLength(NdxFile^.Ndx) + 1 );
- END;
- END ReadNdx;
- VAR
- NdxRebuilt : BOOLEAN;
- BEGIN
- (*OpenNdxFile*)
- NdxTypes.InitNdxFile( NdxFile );
- M2Strings.Assign( FileName, NdxFile^.name );
- IF HandleIO.FindFile( NdxFile^.handle, NdxFile^.name, "path" )
- # StringIO.NoError THEN
- (*Find and open the ndx file if it exists.*)
- NdxFile^.name := "";
- VStorage.DosDealloc( NdxFile, SYSTEM.TSIZE(NdxTypes.NdxRecord) );
- NdxFile := NIL;
- (*Some Storage modules don't nil out the pointer after
- deallocating it, so we do it ourselves.*)
- RETURN FALSE;
- END;
- IF NOT ReadStructure( NdxFile, NdxRebuilt) THEN
- (*Reads the zero record and fills the StructLst in
- NdxFile^.*)
- VStorage.DosDealloc( NdxFile, SYSTEM.TSIZE(NdxTypes.NdxRecord) );
- NdxFile := NIL;
- RETURN FALSE;
- END;
- IF NOT NdxRebuilt THEN
- ReadNdx( NdxFile);
- (*Load a linked list with the record index for this file.*)
- END;
- NdxFile^.FileBufPtr := NIL;
- GenLists.NewList( NdxFile^.ListBuf );
- MakeEmptyBuf( NdxFile^.StructLst, NdxFile^.ListBuf );
- RETURN TRUE;
- END OpenNdxFile;
- PROCEDURE InitBuffer( VAR NdxFile: NdxTypes.NdxFileType; RecName: ARRAY
- OF CHAR): BOOLEAN;
- (* called by PutField and GetField to load the record data
- into the list buffer. If RecordName is already in BufRecName
- RETURNs TRUE. If not, checks to see if RecName exists in
- index. If no, returns FALSE. If OK, retrieves record,
- then moves read buffer into GenList in ListBuf. IF all OK,
- returns TRUE.*)
- VAR
- NameFound: ARRAY [0..NdxTypes.RecNameLength] OF CHAR;
- NameAdr : SYSTEM.ADDRESS;
- NameSize : CARDINAL;
- checkchar: CHAR;
- OffSet: LONGINT;
- UsedSize, AllocatedSize, dumcard: CARDINAL;
- BEGIN
- NdxTypes.CheckInit( NdxFile);
- StrEdit.CrunchBlanks( RecName );
- IF PosUtils.Equal(RecName, NdxFile^.BufRecName) THEN
- RETURN TRUE;
- ELSIF M2Strings.Length(RecName) = 0 THEN
- RETURN FALSE;
- END;
- IF GenLists.Initialized( NdxFile^.ListBuf ) THEN
- GenLists.DisposeList( NdxFile^.ListBuf );
- END;
- IF NOT FindRecord( NdxFile, RecName, OffSet, UsedSize,
- AllocatedSize ) THEN
- GenLists.NewList( NdxFile^.ListBuf );
- MakeEmptyBuf( NdxFile^.StructLst, NdxFile^.ListBuf );
- M2Strings.Assign( RecName, NdxFile^.BufRecName );
- RETURN FALSE;
- END;
- VStorage.DosAlloc( NdxFile^.FileBufPtr, UsedSize );
- NdxFile^.BufSizeNow := UsedSize;
- HandleIO.SetFilePtr(NdxFile^.handle, HandleIO.FromStart, OffSet );
- IF NOT (StringIO.NoError = HandleIO.BlockRead( NdxFile^.handle,
- NdxFile^.FileBufPtr, UsedSize)) THEN
- VStorage.DosDealloc( NdxFile^.FileBufPtr, UsedSize );
- NdxFile^.BufSizeNow := 0;
- RETURN FALSE;
- END;
- LowLevel.Fill( NdxFile^.FileBufPtr, 4 (*SIZE(StartSep) +
- SIZE(TypeCode)*), 0C );
- LowLevel.Fill( LowLevel.AddAddr( NdxFile^.FileBufPtr,
- UsedSize - 2 ), 2, 0C );
- (*These two fills wipe out the startsep and endsep that begin
- and end each record.*)
- M2Strings.Assign( RecName, NdxFile^.BufRecName );
- (* put current record name in BufRecName *)
- GenLists.NewList( NdxFile^.ListBuf );
- GenLists.BlockToList( NdxFile^.FileBufPtr, NdxFile^.BufSizeNow,
- StartSep, EndSep, 0, 0, NdxFile^.ListBuf);
- IF GenLists.ErrorFlag # GenLists.NoListError THEN
- RETURN FALSE;
- END;
- IF GenLists.ListLength( NdxFile^.ListBuf ) > 0 THEN
- StripList( NdxFile^.ListBuf );
- GenLists.GetElmtAdr( NdxFile^.ListBuf, 1, NameAdr,
- NameSize, dumcard );
- (* We want to store the record name in NameFound, but first we
- have to check it so that we can warn intelligently
- in case of file damage. *)
- NameSize := LowLevel.ScanEQ( NameSize, 0C, NameAdr );
- (* Reduce NameSize to length of string before the null. *)
- IF NameSize <= NdxTypes.RecNameLength THEN
- LowLevel.Move( NameAdr, SYSTEM.ADR(NameFound), NameSize + 1 );
- (* It's NameSize + 1 because we have to make sure the trailing
- null gets included in the move. *)
- ELSE
- ErrorNames.WarningName( 'RecDam' );
- END;
- GenLists.ListDelete( NdxFile^.ListBuf, 1, 1 );
- (*Delete the record name from the ListBuf.*)
- ELSE
- MakeEmptyBuf( NdxFile^.StructLst, NdxFile^.ListBuf );
- RETURN TRUE;
- (*Actually something has probably gone wrong here--a
- record has apparently been written to the file that
- doesn't even have the record-bracketing StartSep and
- EndSep. But maybe we're about to correct it, so we
- return TRUE.*)
- END;
- checkchar := NameFound[0];
- M2Strings.Delete(NameFound, 0, 1);
- RETURN PosUtils.Equal( NameFound, RecName )
- (* RecName stored in record read *)
- AND (checkchar # IsGarbageByte);
- (* Successful closing of file last time it was used *)
- END InitBuffer;
- PROCEDURE Retrieve( NdxFile: NdxTypes.NdxFileType; RecordName: ARRAY OF
- CHAR; BufAddr: SYSTEM.ADDRESS; VAR RecSize: CARDINAL): BOOLEAN;
- (* Reads record named into file buffer. Returns TRUE if found,
- FALSE if not. *)
- VAR
- offset: LONGINT;
- ListSpot: CARDINAL;
- BEGIN
- NdxTypes.CheckInit( NdxFile );
- IF NOT FindRecord( NdxFile, RecordName, offset, RecSize,
- ListSpot ) THEN
- (* if RecordName not in index list, return FALSE *)
- RETURN FALSE;
- END;
- HandleIO.SetFilePtr(NdxFile^.handle, HandleIO.FromStart, offset );
- RETURN StringIO.NoError = HandleIO.BlockRead( NdxFile^.handle,
- BufAddr, RecSize);
- END Retrieve;
- PROCEDURE NoRebuild( VAR NdxFile: NdxTypes.NdxFileType );
- BEGIN
- ErrorNames.WarningName( 'NdxDam' );
- END NoRebuild;
- PROCEDURE Init();
- BEGIN
- IF Initialized THEN
- RETURN;
- ELSE
- Initialized := TRUE;
- END;
- (*EntryDiag:
- Diagnostics.Init();
- :EntryDiag*)
- ErrorNames.Init();
- HandleIO.Init();
- GenLists.Init();
- ListUtils.Init();
- LowLevel.Init();
- M2Strings.Init();
- NdxTypes.Init();
- Numbers.Init();
- NumTypes.Init();
- PosUtils.Init();
- StrEdit.Init();
- StringIO.Init();
- VStorage.Init();
- (*EntryDiag:
- Diagnostics.diagS( 'Entering NdxBones', '' );
- :EntryDiag*)
- RebuildProc := NoRebuild;
- CompareProc := M2Strings.CompareStr;
- StartSep[0] := CodeChar;
- StartSep[1] := StartChar;
- EndSep[0] := CodeChar;
- EndSep[1] := EndChar;
- CodedStr[0] := CodeChar;
- CodedStr[1] := EncodedChar;
- NdxMarker[0] := CodeChar;
- NdxMarker[1] := NdxMarkChar;
- StrEdit.AssignStr( "STRUCTURE", StructName);
- (*EntryDiag:
- Diagnostics.diagS( 'Exiting NdxBones', '' );
- :EntryDiag*)
- END Init;
- BEGIN
- Initialized := FALSE;
- Init();
- END NdxBones.
|