home *** CD-ROM | disk | FTP | other *** search
- Program StorageTest;
-
- { This program will demonstrate the ability to save and restore text info
- in an indexed file that is also Network aware. This should be interesting
-
- Note that the information both stored and retrived are limited to 65530
- characters in length. In the current version, this will require you to
- have somewhere on your heap that much space. In the future this routine
- will be made EMS aware so that it will grab the best option for heap
- storage and manipulation out there...
-
- The OBJECT TStorage is a Child of the BufStream Object. This means that
- it still retains all the lower level stuff from BufStream, DOSStream, and
- TStream if you have some sort of use for that.
-
- The routines provided are as follows:
-
- TStorage.Init(FNameStr, Mode, BufSize)
- This routine will initialize the file that you are going to be reading
- from or writing to. You can use the stCreate, stOpenWrite, stOpenRead,
- or stOpen as your mode. If you use the stCreate, the system will write
- over your previous file. If you use stOpenWrite, you can ONLY write
- to the file, you cannot do reads and visa-versa with stOpenRead. If
- you use stOpen, then you can do both operations at the same time.
-
- This is another item that in the future will be changed to do record
- locking of the specified section you are writing to so that other
- users on a network can read from the various other parts of the file.
-
- The BufSize defines the internal buffer size that the system will use
- to buffer your I/O reads. Borland recommends around 1024 for standard
- usage. You might make it bigger or smaller depending on your needs.
-
- TStorage.WriteMsg(Buf)
- This takes a buffer that you define that is NULL terminated (there is
- a #0 at the end of your text) and will write it out to the end of the
- file after running the buffer thru the internal compression routine
- (see TStorage.Compress). It will also set an internal variable
- TStorage.SIndex that is your key to retrieving this body of text.
-
- TStorage.ReadMsg(Buf : PCharBuf; Index)
- This is how you retrieve your text. You pass the index that you got
- earlier from TStorage.SIndex to this routine and it will pass you a
- buffer that is defined as an array of characters [0..whatever] with
- the string being NULL terminated. NOTE: If the index that you pass
- is not the beginning of a stored pattern, the ReadBuf routine will
- assume that you are reading a STANDARD text file and will rewind
- and read the ENTIRE file into the buffer. This is how you can use
- the same routine to read normal text files as well as those created
- by this Object. If the message was deleted by the DeleteMsg routine,
- you will get an errorlevel of 100 (Disk Read Error) returned to you
- from the function.
-
- TStorage.DeleteMsg(Index)
- This function does not actually delete the message out of the stream
- as this would then mess up all subsequent index pointers. Instead, it
- changes the compression routine variable to $FF indicating that the
- message is no longer valid. To actually take the messages out of the
- stream, you need to use the CleanUpMsg procedure.
-
- TStorage.CleanUpMsg
- This procedure will scan the message stream, and re-write it out to a
- seperate file leaving out all the deleted messages. It then creates
- a linked list of the old indexes and their new values. This is then
- used by you, the user, to change all your old saved index values.
- NOTE: Make sure that you do the index change BEFORE calling the
- TStorage.Done routine as this will remove your list from memory and
- all your pointers will be subsiquently screwed up. If there is a
- problem and you need to restore the previous file, you can rename
- .$$$ file back to your filename. The .$$$ file is not deleted until
- the TStorage.Done is called.
-
- TStorage.NewIndex(Index) : LONGINT
- When you call this routine with an old index number, it will return
- to you the new index reference number. You'll get a -1 if the system
- cannot fine an original index number. To use this, you can scan
- through your recorded indexes in your data file sequentially and call
- this routine with each one you get. Then replace the old value with
- the new value. If you get a -1 as your return, then the old message
- was either originally deleted or lost to the system. This will ALWAYS
- return a -1 if you haven't made a VALID call to TStorage.CleanUpMsg.
- It will also reset after a TStorage.Done has been executed. Make sure
- that you use this after the TStorage.CleanUpMsg routine if you want
- to retain the changes made.
-
- TStorage.DeleteCleanUp
- If you decide that for some reason something went wrong somewhere and
- everything is screwed up, you can prevent TStorage.Done from replacing
- your original msg file by calling this routine. It will remove the
- .$$$ file from the disk and clear out all TStorage.NewIndex references.
-
- TStorage.Compress(Buf)
- This is a compression routine that is VERY rudimentary. I whipped
- this up in an hour or so just to demonstrate how it works. You can
- create a child object and replace the compress and decompress routines
- with something more efficient if you'd like. All you need to do is
- create a new RegComp variable other than 1 and make sure that your
- compression routine will downwardly call mine if the numbers don't
- match. This way you can read files that were created with any
- compression routine that is in the line.
-
- TStorage.DeCompress(Buf)
- Same as the compression except that this goes backwards. Again, this
- is a basic one that I whipped together in a matter of minutes so don't
- be too impressed by it
-
- TStorage.Done
- Here is where you clean up all the messes, close all the files, and
- return all the used heap back. Remember to call this when your done
- using the routines
-
- ERRORS Returned
- When you check the TStorage.Status Integer, if you do not get an stOk
- returned, then something went wrong. To identify it from this Unit,
- You can check TStorage.Status against stStoreError. Errors also
- included are stStoreReadErr, stStoreWriteErr, and stStoreUnknownErr.
- These are stored in the TStorage.ErrorInfo location.
-
- ---------------------------------------------------------------------------
-
- These routines were originally designed as a message storage routine for a
- new BBS system message base that we are putting together, however we have
- used this storage format for a varity of purposes as you can store variable
- length messages to one file and only have to keep track of an index. It
- also attempts to save on disk space which is ALWAYS at a premium around
- here.
-
- If you have any suggestions or improvments on this file or its usage, or
- would just like to chat, you can reach me at the following:
-
- Marcos R. Della
- 5084 Rincon Ave.
- Santa Rosa, CA 95409
-
- CIS: 71675,765
-
- ---------------------------------------------------------------------------}
-
- Uses Dos, Crt, Storage, Objects;
-
- VAR T : TStorage;
- st1 : STRING; {Kind of a pseudo buffer}
- st2 : STRING; {Another pseudo buffer}
- st3 : STRING;
- p : PCharBuf; {Pointer to the return character buffer}
-
- idx1 : LONGINT;
- idx2 : LONGINT;
- idx3 : LONGINT;
- loop : WORD;
- ch : CHAR;
- BEGIN
- CLRSCR;
- st1 := 'Now is the time for all good men to come to the aid of their '
- + 'country before the last of the Mohecians take over the world as '
- + 'we now know it. This might be a very detrimental accident if '
- + 'it is allowed to happen' + #0;
- st2 := 'This is a message that will test the deletion function.' + #0;
- st3 := 'This message will survive the compression and deletion!' + #0;
-
- T.Init('TESTFILE.DAT',stOpenWrite,512);
- IF T.ErrorInfo = 2 THEN {File Does Not Exist}
- BEGIN
- T.Done;
- T.Init('TESTFILE.DAT',stCreate,512)
- END;
- WriteLn('Filename: ',T.SFileName);
- WriteLn('Mode: ',T.SMode);
-
- T.WriteMsg(st1[1]); {Our actual buffer is from 1..till we hit the NULL}
- IF T.Status <> stOk THEN {Do your real error checking here if you are}
- T.Reset; {really interested}
- idx1 := T.SIndex;
- WriteLn('1st Index: ',idx1);
-
- T.WriteMsg(st2[1]);
- IF T.Status <> stOk THEN
- T.Reset;
- idx2 := T.SIndex;
- Writeln('2nd Index: ',idx2);
-
- T.WriteMsg(st3[1]);
- IF T.Status <> stOk THEN
- T.Reset;
- idx3 := T.SIndex;
- Writeln('3nd Index: ',idx3);
-
- WriteLn;
- T.DeleteMsg(idx2);
- WriteLn('First Deletion Attempt (Write Only): ',T.ErrorInfo);
- IF T.Status <> stOk THEN
- T.Reset;
- T.Done;
-
- T.Init('TESTFILE.DAT',stOpen,128);
- T.DeleteMsg(idx2); {Must be open for read/write!}
- WriteLn('Second Deletion Attempt (Read/Write): ',T.ErrorInfo);
- IF T.Status <> stOk THEN
- T.Reset;
-
- T.ReadMsg(p,idx2);
- WriteLn('Attempt to re-read: ',T.ErrorInfo);
- IF T.Status <> stOk THEN
- T.Reset;
- Write('"');
- Loop := 0;
- WHILE p^[Loop] <> #0 DO BEGIN
- Write(p^[Loop]);
- INC(Loop)
- END;
- WriteLn('"');
- Write('Cleaning up the deletion files. Error returned: ');
- T.CleanUpMsg;
- WriteLn(T.ErrorInfo);
- WriteLn('Re-Index of #1 (Old/New): ',idx1,'/',T.NewIndex(idx1));
- WriteLn('Re-Index of #2: ',idx2,'/',T.NewIndex(idx2));
- WriteLn('Re-Index of #3: ',idx3,'/',T.NewIndex(idx3));
- WriteLn;
- WriteLn('Removing Cleanup stuff and restoring old indexes');
- T.DeleteCleanUp;
- T.Done;
-
- T.Init('TESTFILE.DAT',stOpenRead,128);
- T.ReadMsg(p,idx1);
- WriteLn('Test that is being read back from the file:');
- WriteLn('---------------Index 1----------------------------');
- Loop := 0;
- WHILE p^[Loop] <> #0 DO BEGIN
- Write(p^[Loop]);
- INC(Loop)
- END;
- WriteLn;
- WriteLn;
-
- T.ReadMsg(p,idx3);
- WriteLn('---------------Index 3----------------------------');
- Loop := 0;
- WHILE p^[Loop] <> #0 DO BEGIN
- Write(p^[Loop]);
- INC(Loop)
- END;
- T.Done;
-
- WriteLn;
- WriteLn('-------------------------------------------');
- WriteLn('If you want to see what the compressed text looks like');
- WriteLn('then use a listing utility to list the file ',T.SFilename);
- WriteLn;
- WriteLn('Press a key to read a STANDARD text file');
- ch := READKEY;
- IF ch = #0 THEN
- ch := READKEY;
- CLRSCR;
-
- T.Init('TEST.PAS',stOpenRead,1024);
- T.ReadMsg(p,0);
- Loop := 0;
- WHILE p^[Loop] <> #0 DO BEGIN
- Write(p^[Loop]);
- INC(Loop)
- END;
- WriteLn;
- T.Done;
- END.
-
-