1.5 The Streams Patterns

A stream is a generalization of internal and external text objects. An internal text object (text) is a sequence (repetition) of chars. An external text object (file) corresponds to a traditional text file. Stream, text and file are organized in the following hierarchy:

Stream, text, and file

stream: (# ... #);
text: stream(# ... #);
file: stream(# ... #);    (* described in a later chapter *)
unixFile: file(# ... #);(* described in a later chapter *)
macFile: file(# ... #); (* described in the Macintosh
                             * Library manual *)

1.5.1 The Stream Pattern

The stream pattern is an abstract superpattern: which provides general stream manipulating procedure patterns: getPos, setPos, eos, length, reset, newline, put, get, peek, putint, getint, puttext, gettext, putline, getNonBlank, getline, getAtom, scan, scanBlanks, scanToNL and scanAtom. The stream pattern also defines exception patterns (e.g. EOSerror). See the interface of stream for more details.

1.5.2 Substreams

There is an additional library called substreams.bet, which implements a substrems concept (and a subtext concept). A substream refers to a (consequtive) portion of another stream. Manipulations on the substream will thereby actually change that portion of this other stream. All usual stream operations applies to a substream. See the interface of substream for more details.

1.5.3 The Text Pattern

The text concept is intended for 'small' texts, but there is no size limit. Some of the operations might however be inefficient on large text objects.

A text is a sequence of characters. The range of a text object T is [1,T.length]. A text can be initialized by executing T.clear or by assigning it with another (initialized) text. Like the predefined patterns integer, real, char and boolean, Text objects are self-assignable. A text constant has the form 'foo' or 'a'. The ' character may by specified as part of a text constant by repeating it, e.g. 'is''s like this' is the text constant: is's like this.

Besides defining the implementations of the abstract stream operations (e.g. put and get), the text pattern defines the following patterns: empty, clear, inxGet, inxPut, append, prepend, scanAll, sub, insert, delete, equal, equalNCS, less, greater, makeLC, makeUC, find, findAll, findText, findTextAll, copy, and asInt.

All error messages from exceptions originating from text objects are followed by the text lines:

Error in text which begins as follows:

where <THIS(text)> is the text where the error occurred.

1.5.4 Text utilities

The library textUtils.bet contains a number of additional text attributes, such as getBoolean, putBoolean, set, setText, setInt, setBased, setReal, and setBoolean. See the interface of textUtils for more details.

The library texthash.bet contains a single operation: honeyman, which is an efficient and nearly optimal hash-function for text hash keys. See the interface of texthash for more details.

1.5.5 Using Text

This example gives examples of how to use the text pattern. The text object Records consists of a sequence of records. Each record has the form:

name Job:aJob Salary:aSalary /

The program shows various patterns for manipulating the Records text:

Program 1: textRecords.bet

ORIGIN '~beta/basiclib/betaenv';

--- program: descriptor --
(* Demo example shwoing examples of how to use the text concept from betaenv.
 * The text object Records, consists of a sequence of records. Each record
 * has the form:
 *    name Job:aJob Salary:aSalary /
 * The program shows various patterns for manipulating the Records text.
(# GetName: (* read next name from T *)
     (# T: ^text; T1: @text
     enter T[]
     do (* scan and skip until a letter is met *)
        T.scan(# while::<(#do NOT (ch->Ascii.isLetter)->value #)#);
        (* scan and read while letters in T *)
        (# while::<(#do ch->Ascii.isLetter->value #)
        do ch->T1.put
     exit T1
     (* Get the record with the name N  and return name and dat part *)
     (# N: ^Text; name,data: @Text
     enter N[]
     do Records.reset;
          (if not Records.eos then
              (* scan and read until '/' is met *)
              Records.scan(# while::<(#do (ch<>'/')->value#) do ch->data.put #);
            (if not (N[]->name.equal) then restart FindName 
     (* get the  job and salary from data part, which is the part after name *)
     (# Data: ^Text; Job: @Text; Salary: @integer
     enter Data[]
     do Data.reset;
        Data[]->GetName; Data.get (* skip ':' *); Data[]->GetName->Job;
        Data[]->GetName; Data.get; Data.GetInt->Salary

   Records: @Text;
do '----------1:'->putLine; 
   (*  initialize Records *)
   'John Job:Programmer salary:120000 / '->Records.append;
   'Joan Job:Doctor salary:130000 / '->Records.append;
   'Mary Job:Boss salary:140000 / '->Records.append;
   (* split Records into atoms *)
     do Records.getAtom->putline; 
        (if Records.eos then leave scan
   (* Find record with name Joan and decode data part *)
   (# Name,Data,Job: @ text; Salary: @Integer
   do 'Joan'->GetRecord->(Name,Data);
      'Ms. '->Name.prePend; 
      ' II'->name.append;
      Name[]->putText; ' has the data: '->putText;
      'Job='->putText; Job.makeUC;  Job[]->putText;
      ' Salary='->putText; Salary->putInt; newline;

1.5.6 UniCode Text

This release contains an experimental implementation of an UniCode stream and UniCode text. The fragment is called wtext.bet, and a UniCode stream is realized by the wstream pattern and a UniCode text is realized by the wtext pattern.

Besides these two patterns, this fragment defines a conversion pattern ascii2wtext, which takes a regular BETA text and converts it into a UniCode text (a wtext instance). Furthermere, this fragment extends the text interface with one additional operation aswtext, which converts the text instance to a wtext instance.

See the interface file for wtext for further details.

Basic Libraries - Reference Manual
© 1990-2002 Mjølner Informatics
[Modified: Friday October 27th 2000 at 13:15]