[net.sources.mac] __StreamLib Documentation

dubois@uwmacc.UUCP (Paul DuBois) (03/17/86)

                    __StreamLib:  A Rascal Library

                           for Stream Input



Introduction
-----------------------------------------------------------------------


__StreamLib comprises a set of routines which allow programs to read
TEXT and/or WORD (MacWrite) files as a stream of characters, without
having to know or care about which type of file is being read.  A
stream can be opened and then read by operations that return either a
character at a time or a line at a time.  There are also sets of
operations that work exclusively on each type of file, should the user
wish to restrict program operation to TEXT files only or to WORD files
only.  Explicit use of a single stream type reduces the amount of code
linked in (although the amount is small).  Use of the routines that
work on both kinds of files incurs a small penalty in code size but
increases the generality of the program:  any program that operates on
simple text files can be made to operate on MacWrite files as well.


To use the library, one first initializes it, then opens a stream and
reads its contents.  Streams are closed automatically when the end of
the stream is reached.  The stream can be read a character or a line at
a time.  Two small programs to read a file and display it follow.

        Proc CharReadStream (); (* read stream a character at a time *)
        Var
                c: Integer;
        {
                InitStream ();
                if OpenStream () <> noErr then
                {
                        loop (,,,)
                        {
                                c := StreamGetC ();
                                if c = -1 then
                                        break;  (* end of stream *)
                                WriteChar (c);
                                if c = ' then
                                        WriteChar (');
                        };
                };
        };


        Proc LineReadStream (); (* read stream a line at a time *)
        Var
                buf: Byte[512]; (* should be big enough! *)
        {
                InitStream ();
                if OpenStream () <> noErr then
                {
                        loop (,,,)
                        {
                                if StreamGetS (buf) = nil then
                                        break;  (* end of stream *)
                                WriteString (buf);
                                WriteLn ();
                        };
                };
        };

If one wishes to know something about the stream, the procedure
GetStreamInfo is available.  This returns a copy of the SFReply used to
open the stream (i.e., it contains the file name, file type, and volume
reference number.

Most of the routines in __StreamLib are described below.  Routines with
names beginning with an underscore are primarily intended for internal
use, but they might be useful in certain contexts.


Stream Initialization, Opening and Closing
-----------------------------------------------------------------------


Procedure InitStream ();

This procedure must be called to set up the library before any other
stream operations are done.


Function OpenStream (): OSErr;

Open a stream.  Closes any currently open stream, then displays a
GetFile dialog listing both TEXT and WORD files.


Function OpenTextStream (): OSErr;

Like OpenStream, but for TEXT files only.


Function OpenWordStream (): OSErr;

Like OpenStream, but for WORD files only.


OpenStream, OpenTextStream and OpenWordStream return:

        noErr           stream opened successfully
        fnOpnErr        stream not opened successfully
        mFulErr         (occurs for WORD files only) stream could be
                        opened, but there was not enough memory to read
                        in initialization information (the stream is
                        closed before returning)


Procedure CloseStream ();

Close the currently open stream.  The character and line input routines
(described below) close the stream automatically upon reaching end of
stream, but CloseStream may be called safely any time after InitStream
is called (even before the first stream is opened!).


Character Input Routines
-----------------------------------------------------------------------


Function StreamGetC (): Integer;

Determine the type of the stream and get the next character
appropriately.


Function TextStreamGetC (): Integer;

Get the next character from the currently open TEXT stream.  Results
meaningless if the stream is a WORD stream.


Function WordStreamGetC (): Integer;

Get the next character from the currently open WORD stream.  Results
meaningless if the stream is a TEXT stream.


StreamGetC, TextStreamGetC and WordStreamGetC return:

        -1              end of stream
        otherwise       next character of stream

Note that the result must be assigned to an integer variable, since -1
is not a legal byte value.

When the end of the stream is reached, these routines close the stream.
Further calls return -1 repeatedly until another stream is opened.


Line Input Routines
-----------------------------------------------------------------------


Function StreamGetS (str: StringPtr): StringPtr;

Determine the type of the stream and get the next line appropriately.
Place the line in the given string.


Function TextStreamGetS (str: StringPtr): StringPtr;

Get the next line (all characters up to the next carriage return or end
of stream) from the currently open TEXT stream.  Place the line in the
given string.  The carriage return is not placed in the string.
Results meaningless if the stream is a WORD stream.


Function WordStreamGetS (str: StringPtr): StringPtr;

Get the next line from the currently open WORD stream.  A "line" is
defined as a string of characters up to the next carriage return or end
of stream, or up to the first space past the current linewrap length.
Lines must be broken at some point, since WORD files contain carriage
returns only at the ends of paragraphs, and it cannot be assumed that
paragraphs will be less than any reasonable length.  Therefore, once a
certain number of characters have been read without a carriage return
being found, the next space causes the call to terminate.  (If you
really need to read in a whole paragraph, use WordStreamGetC until it
returns a carriage return.)

The line is placed in the given string.  The carriage return (or space
if the line is broken) is not placed in the string.  Results
meaningless if the stream is a TEXT stream.


StreamGetS, TextStreamGetS and WordStreamGetS return:

        nil             end of stream
        otherwise       pointer to the argument

When the end of the stream is reached, these routines close the stream.
Further calls return nil repeatedly until another stream is opened.


Miscellaneous Routines
-----------------------------------------------------------------------


Procedure GetStreamInfo (streamInfo: SFReply);

Returns, in the argument, a copy of the SFReply record used to open the
stream (from which the file name, file type and file volume reference
number can be determined).  This information is meaningless unless a
stream is actually open.


Procedure SetLineLen (len: Integer);

Sets the line wrap length for WordStreamGetS.


Function _FSOpen (fName: PtrB; vRefNum: Integer; refNum: ^Integer;
                                mode: Integer): OSErr;

This function is similar to FSOpen (in Inside Macintosh) except that it
allows an open mode to be specified.


Procedure _ffRead (f: Integer; b: PtrB; amount: LongInt);

Reads amount bytes from the file f into the buffer pointed to by b.


Procedure _fMoveTo (f: Integer; pos: LongInt);

Moves to position pos in file f.


Limitations
-----------------------------------------------------------------------


Only one file at a time can be streamed.


Acknowledgments
-----------------------------------------------------------------------


The code which extracts the text from WORD files is modelled after the
programs ReadMacWrite and Index, by Scott Gillespie (Reed College).
Scott is of course not responsible for any glaring ugliness in my code.
The main differences between his code and mine are:  In ReadMacWrite
the text extractor is a high-level routine that repeatedly passes
characters to subsidiary routines, while in __SteamLib the extractor is
a subsidiary routine repeatedly called by higher-level operations in
the host program.  Also, I used a Handle rather than a Ptr for reading
in each paragraph.  I found that DA's using the library would not
execute properly when they were run inside of other programs not
created with Rascal - SetPtrSize always failed.  I don't know why.

-- 
                                                                    |
Paul DuBois     {allegra,ihnp4,seismo}!uwvax!uwmacc!dubois        --+--
                                                                    |
                                                                    |