eXept Software AG Logo

Smalltalk/X Webserver

Documentation of class 'ExternalStream':

Home

Documentation
www.exept.de
Everywhere
for:
[back]

Class: ExternalStream


Inheritance:

   Object
   |
   +--Stream
      |
      +--PeekableStream
         |
         +--PositionableStream
            |
            +--WriteStream
               |
               +--ReadWriteStream
                  |
                  +--ExternalStream
                     |
                     +--ExternalReadStream
                     |
                     +--ExternalWriteStream
                     |
                     +--FileStream
                     |
                     +--NonPositionableExternalStream

Package:
stx:libbasic
Category:
Streams-External
Version:
rev: 1.599 date: 2024/03/13 13:58:33
user: cg
file: ExternalStream.st directory: libbasic
module: stx stc-classLibrary: libbasic

Description:


ExternalStream defines protocol common to Streams which have a file-descriptor and
represent some file or communicationChannel of the underlying OperatingSystem.
ExternalStream is abstract; concrete classes are FileStream, PipeStream etc.

ExternalStreams can be in two modes: text- (the default) and binary-mode.
In text-mode, the elements read/written are characters;
while in binary-mode the basic elements are bytes which read/write as SmallIntegers
in the range 0..255.

Also, the stream can be either in buffered or unbuffered mode. In buffered mode,
data is not written until either a cr is written (in text mode) or a synchronizeOutput
is sent (in both modes).

The underlying OperatingSystem streams may either be closed explicitely (sending a close)
or just forgotten - in this case, the garbage collector will eventually collect the
object AND a close will be performed automatically (but you will NOT know when this
happens - so it is recommended, that you close your files when no longer needed).
Closing is also suggested, since if smalltalk is finished (be it by purpose, or due to
some crash) the data will not be in the file, if unclosed.
All streams understand the close message, so it never hurts to use it (it is defined as
a noop in one of the superclasses).

Most of the methods found here redefine inherited methods for better performance,
since I/O from/to files should be fast.

Recovering a snapshot:
  not all streams can be restored to the state they had before - see the implementation of
  reOpen in subclasses for more information.
  For streams sitting on some communication channel (i.e. Pipes and Sockets) you should
  reestablish the stream upon image restart (make someone dependent on ObjectMemory).
  FileStreams are reopened and positioned to their offset they had at snapshot time.
  This may fail, if the file was removed or renamed - or lead to confusion
  if the contents changed in the meantime.
  Therefore, it is a good idea to reopen files and check for these things at restart time.

[Instance variables:]

    handleType      <Symbol>        desribes what handle is:
                                        win32: #fileHandle, #socketHandle,
                                               #filePointer, #socketFilePointer, #pipeFilePointer
                                        unix: #filePointer, #socketFilePointer, #pipeFilePointer
                                    needed for win32, which uses different APIs for the different handles (sigh)
    handle          <Integer>       used to be always a filePointer somehow mapped to an integer (FILE* - not the fd);
                                    now, either a filePointer or a handle (win32)
    mode            <Symbol>        #readwrite, #readonly or #writeonly
    buffered        <Boolean>       true, if buffered (i.e. collects characters - does
                                    not output immediately)
    binary          <Boolean>       true if in binary mode (reads bytes instead of chars)
    eolMode         <Symbol>        one of nil, #nl, #cr or #crlf.
                                    determines how lines should be terminated.
                                    nil -> newLine (as in Unix);
                                    #crlf -> with cr-lf (as in MSDOS)
                                    #cr -> with cr (as in VMS)
    hitEOF          <Boolean>       true, if EOF was reached

    lastErrorNumber <Integer>       the value of errno (only valid right after the error -
                                    updated with next i/o operation)

[Class variables:]
    Lobby           <Registry>      keeps track of used ext-streams (to free up FILE*'s)

    StreamErrorSignal       <Signal> parent of all stream errors (see Stream class)
    InvalidReadSignal       <Signal> raised on read from writeonly stream
    InvalidWriteSignal      <Signal> raised on write to readonly stream
    InvalidModeSignal       <Signal> raised on text I/O with binary-stream
                                     or binary I/O with text-stream
    OpenErrorSignal         <Signal> raised if open fails
    StreamNotOpenSignal     <Signal> raised on I/O with non-open stream

Additional notes:
  This class is implemented using the underlying stdio-c library package, which
  has both advantages and disadvantages: since it is portable (posix defined), porting
  ST/X to non-Unix machines is simplified. The disadvantage is that the stdio library
  has big problems handling unbounded Streams, since the EOF handling in stdio is
  not prepared for data to arrive after EOF has been reached - time will show, if we need
  a complete rewrite for UnboundedStream ...

  Also, depending on the system, the stdio library behaves infriendly when signals
  occur while reading (for example, timer interrupts) - on real unixes (i.e. BSD) the signal
  is handled transparently - on SYS5.3 (i.e. non unixes :-) the read operation returns
  an error and errno is set to EINTR.
  That's what the ugly code around all getc-calls is for ...
  Since things get more and more ugly - we will rewrite ExternalStream
  completely, to NOT use any stdio stuff (and do its buffering itself).

  Notice that typical stdio's use a single errno global variable to return an error code,
  this was bad design in the stdio lib (right from the very beginning), since it's much
  harder to deal with this in the presence of lightweight processes, where errno gets
  overwritten by an I/O operation done in another thread. (stdio should have been written
  to return errno as a negative number ...).
  To deal with this, the scheduler treats errno like a per-thread private variable,
  and saves/restores the errno setting when switching to another thread.
  (Notice that some thread packages do this also, but ST/X's thread implementation
  does not depend on those, but instead uses a portable private package).

  Finally, if an stdio-stream is open for both reading and writing, we have to call
  fseek whenever we are about to read after write and vice versa.
  Two macros (__READING__ and __WRITING__) have been defined to be used before every
  fread/fgetc and fwrite/putc respectively.

copyright

COPYRIGHT (c) 1988 by Claus Gittinger All Rights Reserved This software is furnished under a license and may be used only in accordance with the terms of that license and with the inclusion of the above copyright notice. This software may not be provided or otherwise made available to, or used by, any other person. No title to or ownership of the software is hereby transferred.

Class protocol:

Signal constants
o  inaccessibleSignal
ST-80 compatibility: return openErrorSignal

o  invalidModeSignal
return the signal raised when doing text-I/O with a binary stream
or binary-I/O with a text stream

o  invalidOperationSignal
return the signal raised when an unsupported or invalid
I/O operation is attempted

o  invalidReadSignal
return the signal raised when reading from writeonly streams

o  invalidWriteSignal
return the signal raised when writing to readonly streams

o  openErrorSignal
return the signal raised when a file open failed

o  streamIOErrorSignal
return the signal raised when an I/O error occurs.
(for example, a device-IO-error, or reading an NFS-dir,
which is no longer available and has been mounted soft)

o  streamNotOpenSignal
return the signal raised on I/O with closed streams

accessing
o  openStreams
answer a collection of open Streams having this class

Usage example(s):

	self openStreams
	Socket openStreams
	NonPositionableExternalStream openStreams

class initialization
o  closeFiles
close all files.
To be called on exit of Smalltalk.

o  initDefaultEOLMode
unix EOL conventions

o  initModeStrings
initialize modeStrings which are passed down to the underlying
fopen/fdopen functions.

o  initialize
self patchByteOrderOptimizedMethods

o  patchByteOrderOptimizedMethods
EXPERIMENTAL (not yet done by default):
change the underlying implementation of
nextPutInt16MSB / nextPutInt16LSB
nextPutInt32MSB / nextPutInt32LSB
to the corresponding NATIVE methods.

o  reOpenFiles
reopen all files (if possible) after a snapShot load.
This is invoked via the #earlyRestart change notification.

o  update: something with: aParameter from: changedObject
have to reopen files when returning from snapshot

defaults
o  defaultCopyBufferSize: anInteger
allows changing the size of buffer used when copying big
files/buld data from one stream to another.
Due to a bug on older Windows systems, the default used in copyToEndInto:
is chosen very conservatively, as the copy used to fail with big buffers.
However, modern Windows systems seem to not suffer from that bug,
and bigger buffer sizes will dramatically increase the performance of
copies to/from network drives.
This method allows for fine tuning, in case you run into performance problems,
or network buffer failures.
When nil, a somewhat conservative compromise is used.

error handling
o  errorReporter
I know about error codes

o  lastErrorNumber
return the errno of the last error

Usage example(s):

     ExternalStream lastErrorNumber

o  lastErrorString
return a message string describing the last error

Usage example(s):

     ExternalStream lastErrorString

o  reportOn: anErrorSymbolOrNumber
an error occurred.
Report it via an Exception

instance creation
o  forFileDescriptor: aFileDescriptor mode: modeSymbol
given a fileDescriptor, create an ExternalStream object
to operate on this fd.
The modeSymbol-argument is #readonly, #readwrite, ....
This may be used to wrap fd's as returned by user
primitive code, or to wrap pipe-fds into externalStreams.

Usage example(s):

     the example below will probably fail (15 is a random FD):

     |s|

     s := ExternalStream forFileDescriptor:15 mode:'r'.
     s next.

o  forFileDescriptor: aFileDescriptor mode: modeSymbol buffered: buffered handleType: handleTypeSymbol
given a fileDescriptor, create an ExternalStream object
to operate on this fd.
The modeSymbol-argument is #readonly, #readwrite, ....
This may be used to wrap fd's as returned by user
primitive code, or to wrap pipe-fds into externalStreams.

Usage example(s):

     the example below will probably fail (15 is a random FD):

     |s|

     s := ExternalStream forFileDescriptor:15 mode:#readonly buffered:false handleType:#filePointer.
     s next.

o  forReadWriteToFileDescriptor: aFileDescriptor
given a fileDescriptor, create an ExternalStream object
to read/write from/to this fd. This may be used to wrap fd's
as returned by user primitive code, or to wrap pipe-
filedescriptors into externalStreams.

Usage example(s):

     the example below will probably fail (15 is a random FD):

     |s|

     s := ExternalStream forReadWriteToFileDescriptor:15.
     s next.

o  forReadingFromFileDescriptor: aFileDescriptor
given a fileDescriptor, create an ExternalStream object
to read from this fd. This may be used to wrap fd's
as returned by user primitive code, or to wrap pipe-
filedescriptors into externalStreams.

Usage example(s):

     the example below will probably fail (15 is a random FD):

     |s|

     s := ExternalStream forReadingFromFileDescriptor:15.
     s next.

Usage example(s):

     |pipe readFd writeFd rs ws|

     'create OS pipe ...'.

     pipe := OperatingSystem makePipe.
     readFd := pipe at:1.
     writeFd := pipe at:2.

     'connect Smalltalk streams ...'.

     rs := ExternalStream forReadingFromFileDescriptor:readFd.
     ws := ExternalStream forWritingToFileDescriptor:writeFd.

     'read ...'.
     [
	 1 to:10 do:[:i |
	     Transcript showCR:rs nextLine
	 ].
	 rs close.
     ] forkAt:7.

     'write ...'.
     [
	 1 to:10 do:[:i |
	     ws nextPutAll:'hello world '; nextPutAll:i printString; cr
	 ].
	 ws close.
     ] fork.

o  forWritingToFileDescriptor: aFileDescriptor
given a fileDescriptor, create an ExternalStream object
to write to this fd. This may be used to wrap fd's
as returned by user primitive code, or to wrap pipe-
filedescriptors into externalStreams.

Usage example(s):

     the example below will probably fail (15 is a random FD):

     |s|

     s := ExternalStream forWritingToFileDescriptor:15.
     s binary.
     s nextPut:1.

o  new
re-enable new - disabled in Stream superclass

obsolete
o  makePTYPair
obsolete since 12-07-2003

** This is an obsolete interface - do not use it (it may vanish in future versions) **

o  makePipe
obsolete since 12-07-2003

** This is an obsolete interface - do not use it (it may vanish in future versions) **

resereved filedescriptors
o  ensureReservedFileDescriptors: countOrNil
make sure that countOrNil fileDescriptors are reserved for emergency cases.
If countOrNil is nil, use the inital allocation as count.
Answer the number of descriptors that have been allocated.

o  freeReservedFileDescriptors: count
free count fileDescriptors;
used for emergency cases (eg. to emergency-save a modified project in expecco)

testing
o  isAbstract
Return if this class is an abstract class.
True is returned here for myself only; false for subclasses.
Abstract subclasses must redefine this again.


Instance protocol:

Compatibility-Dolphin
o  beText

Compatibility-Squeak
o  nextInto: aByteArrayOrString
read elements into the argument, whose size determines the amount
of bytes to read. If not enough elements could be read, return
a copy of the argument; otherwise, return the filled argument.

o  readInto: aContainer startingAt: index count: nElements
same as #nextBytes:into:startingAt: for ByteArrays;
for LongArrays, nelements longs are read.
Squeak compatibility.

o  readOnly
Squeak compatibility: make the stream readOnly

Signal constants
o  invalidReadSignal

o  invalidWriteSignal

accessing
o  binary
switch to binary mode - default is text

o  binary: beBinaryBool
switch to binary mode if beBinaryBool is true.
Returns the previous mode.
The initial default is text

o  buffered: aBoolean
turn buffering on or off - default is on.
Answer the previous bufferd state.

o  contents
return the contents of the file from the current position up-to
the end. If the stream is in binary mode, a ByteArray containing
the byte values is returned.
In text-mode, a collection of strings, each representing one line,
is returned.

o  contentsAsString
to compensate for the bad naming, use this to make things explicit.
See also #contents, which returns the lines as stringCollection for textFiles.

o  contentsOfEntireFile
ST-80 compatibility: return contents as a String (or byteArray, if in binary mode).
See also #contents, which returns the lines as stringCollection for text files.

o  contentsSpecies
return the kind of object to be returned by sub-collection builders
(such as upTo)

o  dependents
(comment from inherited method)
return a Collection of dependents.
The default implementation here uses a global WeakDictionary to store
dependents
This may be too slow for high frequency change&update,
therefore, some classes (Model) redefine this for better performance.
Notice the mentioning of a WeakDictionary - read the classes documentation.

o  dependents: aDependentsCollection
(comment from inherited method)
set the collection of dependents.
The default implementation here uses a global Dictionary to store
dependents which may be too slow for high frequency change&update.
Therefore, some classes (Model) redefine this for better performance.

o  eolMode
return how end-of-line (EOL) is to be marked.
Returns one one of:
#crlf -> add a CR-NL, as in MSDOS
#cr -> add a CR, as in VMS
#nl -> add a NL, as in Unix
#eot -> add an EOT (= 0x04, as used in some modems/protocols)
#etx -> add an ETX (= 0x03, as used in some modems/protocols)
#nl -> add a NL, as in Unix
nil -> transparent

o  eolMode: aSymbolOrNil
specify how end-of-line (EOL) is to be marked.
The argument may be one of:
#crlf -> add a CR-NL, as in MSDOS
#cr -> add a CR, as in VMS
#nl -> add a NL, as in Unix
#eot -> add an EOT (= 0x04, as used in some modems/protocols)
#etx -> add an ETX (= 0x03, as used in some modems/protocols)
anyOther -> like #nl

o  fileDescriptor
return the fileDescriptor of the receiver -
notice: this one returns the underlying OSs fileDescriptor -
this may not be available on all platforms (i.e. non unix systems).

NOTE: this may set the handle instance variable to nil
if the file descriptor is no longer valid.

o  fileDescriptorOfFile: aHandle
for migration to rel5 only:
return the fileDescriptor of the argument handle -
notice: this one returns the underlying OSs fileDescriptor -
this may not be available on all platforms (i.e. non unix systems).

o  fileHandle
return the fileHandle of the receiver.
Under unix, this is the fileDescriptor; under windows, this is the Handle.

NOTE: this may set the handle instance variable to nil
if the file descriptor is no longer valid.

o  filePointer
return the filePointer of the receiver -
notice: for portability stdio is used; this means you will get
a FILE * - not a fileDescriptor.
(what you really get is a corresponding integer).
You cannot do much with the returned value
- except passing it to a primitive, for example.

o  handle

o  handleType

o  lineEndCR
(comment from inherited method)
Ignored here, but added to make internalStreams protocol compatible
with externalStreams.

o  lineEndCRLF

o  lineEndLF

o  lineEndTransparent

o  pathName
answer the pathName of the stream.
Only FileStreams know the pathName, so we return an empty string here

o  readonly
set access mode to readonly

o  readwrite
set access mode to readwrite

o  text
switch to text mode - default is text

o  useCRLF: aBoolean
turn on or off CRLF sending (instead of LF only) - default is off.
This method is provided for backward compatibility - see #eolMode:
which offers another choice.

** This is an obsolete interface - do not use it (it may vanish in future versions) **

o  writeonly
set access mode to writeonly

closing
o  abortAndClose
close the stream - added for protocol compatibility with Socket and PipeStream.
see comment there

o  close
Close the stream.
No error if the stream is not open.

o  shutDown
close the stream - added for protocol compatibility with Socket.
see comment there

copying
o  copy
answer a copy of myself.
Have to dup the filedescriptor and position the copy

Usage example(s):

       |stream1 stream2|

       stream1 := Filename newTemporary writeStream.
       stream2 := stream1 copy.

       stream1 inspect.
       stream2 inspect.

defaults
o  bufferSizeForBulkCopy
return the size of buffer used when copying big files/bulk data
from one stream to another.
Due to a bug on older Windows systems, the default used
is chosen very conservatively, as the copy used to fail with big buffers.
However, modern Windows systems seem to not suffer from that bug,
and bigger buffer sizes will dramatically increase the performance of
copies to/from network drives.
Setting DefaultCopyBufferSize allows for fine tuning,
in case you run into performance problems, or network buffer failures.
When nil, a somewhat conservative compromise is used.

error handling
o  argumentMustBeCharacter
report an error, that the argument must be a character in 0..FF

o  argumentMustBeInteger
report an error, that the argument must be an integer

o  argumentMustBeString
report an error, that the argument must be a string

o  errorAlreadyOpen
report an error, that the stream is already opened

Usage example(s):

      self new errorAlreadyOpen

o  errorBinary
report an error, that the stream is in binary mode

o  errorNotBinary
report an error, that the stream is not in binary mode

o  errorNotBuffered
report an error, that the stream is not in buffered mode

o  errorReadOnly
report an error, that the stream is a readOnly stream

o  errorReporter
ST-80 mimicry.

o  errorUnsupportedOperation
report an error, that some unsupported operation was attempted

o  errorWriteOnly
report an error, that the stream is a writeOnly stream

o  ioError
report an error, that some I/O error occurred.
(for example, a device-IO-error, or reading an NFS-dir,
which is no longer available and has been mounted soft)

o  ioError: errorNumber
report an error, that some I/O error occurred.
(for example, a device-IO-error, or reading an NFS-dir,
which is no longer available and has been mounted soft)

o  lastErrorHolder
return an ErrorHolder object for the last error

o  lastErrorNumber
return the last error

o  lastErrorString
return a message string describing the last error

o  lastErrorSymbol
return an error symbol describing the last error

o  openError
report an error, that the open failed

** This is an obsolete interface - do not use it (it may vanish in future versions) **

o  openError: errorNumber
report an error, that the open failed

o  readError
report an error, that some read error occurred

o  readError: errorNumber
report an error, that some read error occurred

o  reportLastError
raise an error.
To be used with calls (e.g. some socket calls), that do not raise an error but
return false on error.

o  writeError
report an error, that some write error occurred

o  writeError: errorNumber
report an error, that some write error occurred

finalization
o  beExecutor
mark myself as being an executor for finalization.
We mis-use the mode symbol for this.

o  executor
return a copy for finalization-registration;
since all we need at finalization time is the fileDescriptor,
a cheaper copy is possible.

o  finalizationLobby
answer the registry used for finalization.
ExternalStreams have their own Registry

o  finalize
some Stream has been collected - close the file if not already done

o  registerForFinalization
keep myself in newSpace, so it will be finalized early

o  unregisterForFinalization
probably the object will be collected soon...

initialization
o  initialize
(comment from inherited method)
just to ignore initialize to objects which do not need it

o  initializeEOLMode

line reading/writing
o  nextLine
read the next line (characters up to newline).
Return a string containing those characters excluding the newline.
If the previous-to-last character is a cr, this is also removed,
so it's possible to read alien (i.e. ms-dos) text as well.
The line must be shorter than 32K characters - otherwise an error is signalled.

o  nextPutLine: aString
write the characters in aString and append an end-of-Line marker
(LF, CR or CRLF - depending in the setting of eolMode)

o  nextPutLinesFrom: aStream upToLineStartingWith: aStringOrNil
read from aStream up to and including a line starting with aStringOrNil
and append all lines to self.
Can be used to copy/create large files or copy from a pipe/socket.

If aStringOrNil is nil or not matched, copy proceeds to the end.

o  peekForLineStartingWith: aString
read ahead for next line starting with aString;
return the line-string if found, or nil if EOF is encountered.
If matched, do not advance position beyond that line
i.e. nextLine will read the matched line.
If not matched, reposition to original position for further reading.

o  peekForLineStartingWithAny: aCollectionOfStrings
read ahead for next line starting with any of aCollectionOfStrings;
return the index in aCollection if found, nil otherwise..
If no match, do not change position; otherwise advance right before the
matched line so that nextLine will return this line.

misc functions
o  async: aBoolean
set/clear the async attribute - if set, the availability of data on
the receiver will trigger an ioInterrupt.
If cleared (which is the default) no special notification is made.
Notice:
not every OS supports this
- check with OS>>supportsIOInterrupts before using

o  blocking: aBoolean
set/clear the blocking attribute - if set (which is the default)
a read (using next) on the receiver will block until data is available.
If cleared, a read operation will immediately return with a value of
nil.
Turning off blocking is useful when reading from PipeStreams
or Sockets, and the amount of data to be read is not known
in advance. However, the data must then be read using #nextBytes:
methods, in order to avoid other (pastEndRead) exceptions.

o  ioctl: ioctlNumber
to provide a simple ioctl facility - an ioctl is performed
on the underlying file; no arguments are passed.

o  ioctl: ioctlNumber with: arg
to provide a simple ioctl facility - an ioctl is performed
on the underlying file; the argument is passed as argument.
This is not used by ST/X, but provided for special situations
- for example, to control proprietrary I/O devices.

Since the type of the argument depends on the ioctl being
performed, different arg types are allowed here.
If the argument is nil, an ioctl without argument is performed.
If the argument is an integral number, it's directly passed;
if it's a kind of ByteArray (ByteArray, String or Structure),
or external data (ExternalBytes or ExternalAddress),
a pointer to the data is passed.
This allows performing most ioctls
- however, it might be tricky to setup the buffer.
Be careful in what you pass - ST/X cannot validate its correctness.

o  reset
set the read position to the beginning of the collection

o  setToEnd
redefined since it must be implemented differently

** This method must be redefined in concrete classes (subclassResponsibility) **

o  sync
make sure, that the OS writes cached data to the disk

Usage example(s):

	|f|
	f := 'x' asFilename writeStream.
	f nextPutAll:'hallo'; sync; syncData; close

o  syncData
make sure, that the OS writes cached data to the disk.
In this case, metadata is only written, if it is
required to read the file's data (so metadata will not be written,
if only access/modification time has changed).

Usage example(s):

	|f|
	f := 'x' asFilename writeStream.
	f nextPutAll:'hallo'; sync; syncData; close

o  tcgetattr
unix only:
provide the information of a tcgetattr call as a dictionary.
This provides terminal setting values of a tty or pty.
Used by terminal emulators.
On non-unix systems, an unsupported operation error is raised

Usage example(s):

the system does not support tcgetattr

Usage example(s):

     Stdin tcgetattr

non homogenous reading
o  next: count into: aCollection startingAt: start
return the next count bytes or characters from the stream.

o  nextAvailable: count
return the next count elements of the stream as aCollection.
If the stream reaches the end before count elements have been read,
return what is available. (i.e. a shorter collection).
The type of collection is specified in #contentsSpecies.

Usage example(s):

     (ReadStream on:#(1 2 3 4 5)) nextAvailable:3
     (ReadStream on:#(1 2 3 4 5)) nextAvailable:10
     (ReadStream on:'hello') nextAvailable:3
     (ReadStream on:'hello') nextAvailable:10

o  nextAvailable: count into: aCollection startingAt: pos
store the next count elements of the stream into aCollection at position pos.
Answer the number of bytes read.

o  nextAvailableBytes: count
return the next count bytes of the stream as a byteArray.
If the stream reaches the end before count bytes have been read,
return what is available. (i.e. a shorter byteArray).

o  nextAvailableBytes: count into: anObject startingAt: start
read the next count bytes into an object and return the number of
bytes read or the number of bytes read, if EOF is encountered before,
or no more bytes are available for reading (from the pipe/socket).

If the receiver is some socket/pipe-like stream, an exception
is raised if the connection is broken.

Notice, that in contrast to other methods,
this does NOT return nil on EOF, but the actual count.
Thus allowing read of partial blocks.

The object must have non-pointer indexed instvars
(i.e. it must be a ByteArray, String, Float- or DoubleArray).
If anObject is a string or byteArray and reused, this provides the
fastest possible physical I/O (since no new objects are allocated).

Use with care - non object oriented I/O.
Warning: in general, you cannot use this method to pass data from other
architectures since it does not care for byte order or float representation.

o  nextAvailableBytesInto: aBuffer
read up to buffer-size bytes of the stream into aBuffer.
Return the number of bytes read
(i.e. either the buffer's size or the number of bytes actually read into it)

o  nextByte
read the next byte and return it as an Integer; return nil on error.
This is allowed in both text and binary modes, always returning the
bytes binary value as an integer in 0..255.

o  nextBytes: countIn into: anObject startingAt: startIn
read the next count bytes into an object and return the number of
bytes read or the number of bytes read, if EOF is encountered before.
If the receiver is some socket/pipe-like stream, an exception
is raised if the connection is broken.

Warning: if used with a pipe/socket, this blocks until the requested number
of bytes have been read. See #nextAvailableBytes:into:startingAt:
to only read whats there.

Notice, that in contrast to other methods,
this does NOT return nil on EOF, but the actual count.
Thus allowing read of partial blocks.

The object must have non-pointer indexed instvars
(i.e. it must be a ByteArray, String, Float- or DoubleArray),
or an externalBytes object (with known size).
If anObject is a string or byteArray and reused, this provides the
fastest possible physical I/O (since no new objects are allocated).

Use with care - non object oriented I/O.
Warning: in general, you cannot use this method to pass data from other
architectures (unless you prepared the buffer with care),
since it does not care for byte order or float representation.

o  nextInt16MSB: msbFlag
Read two bytes and return the value as a 16-bit signed Integer.
If msbFlag is true, value is read with most-significant byte first,
otherwise least-significant byte comes first.
A nil is returned if EOF is reached (also when EOF is hit after the first byte).
Works in both binary and text modes.

o  nextInt32MSB: msbFlag
Read four bytes and return the value as a 32-bit signed Integer,
which may be a LargeInteger.
If msbFlag is true, value is read with most-significant byte first,
otherwise least-significant byte comes first.
A nil is returned, if EOF is hit before all 4 bytes have been read.
Works in both binary and text modes.

o  nextUnsignedInt16MSB: msbFlag
Read two bytes and return the value as a 16-bit unsigned Integer.
If msbFlag is true, value is read with most-significant byte first,
otherwise least-significant byte comes first.
A nil is returned if EOF is reached (also when EOF is hit after the first byte).
Works in both binary and text modes.

o  nextUnsignedInt32MSB: msbFlag
Read four bytes and return the value as a 32-bit unsigned Integer, which may be
a LargeInteger.
If msbFlag is true, value is read with most-significant byte first, otherwise
least-significant byte comes first.
A nil is returned, if endOfFile occurs before all 4 bytes have been read.
Works in both binary and text modes.

o  nextWord
in text-mode:
read the alphaNumeric next word (i.e. up to non letter-or-digit).
return a string containing those characters.
in binary-mode:
read two bytes (msb-first) and return the value as a 16-bit
unsigned Integer (for compatibility with other smalltalks)

** This is an obsolete interface - do not use it (it may vanish in future versions) **

non homogenous writing
o  nextPutByte: aByteValue
write a byte.
Works in both binary and text modes.

o  nextPutInt16: anIntegerOrCharacter MSB: msbFlag
Write the argument, anIntegerOrCharacter as a short (two bytes).
If msbFlag is true, data is written most-significant byte first;
otherwise least first.
Notice that integers in the range 16r-8000 to +16rFFFF can be written
(i.e. both signed and unsigned int32 values can be written.
Works in both binary and text modes.

o  nextPutInt16LSB: anIntegerOrCharacter
do not remove.
See #patchByteOrderOptimizedMethods

o  nextPutInt16MSB: anIntegerOrCharacter
do not remove.
See #patchByteOrderOptimizedMethods

o  nextPutInt16NATIVE: anIntegerOrCharacter
Write the argument, anIntegerOrCharacter as a short (two bytes) in native byte order.
This is the CPU-specific byte order (LSB on x86 and VAX, MSB on sparc, and possibly on ARM).
Notice that integers in the range 16r-8000 to +16rFFFF can be written
(i.e. both signed and unsigned int32 values can be written.
Works in both binary and text modes.

o  nextPutInt32: aNumber MSB: msbFlag
Write the argument, aNumber as a long (four bytes).
If msbFlag is true, data is written most-significant byte first;
otherwise least first.
Notice that integers in the range 16r-80000000 to +16rFFFFFFFF can be written
(i.e. both signed and unsigned int32 values can be written.
Works in both binary and text modes.

o  nextPutInt32LSB: anIntegerOrCharacter
do not remove.
See #patchByteOrderOptimizedMethods

o  nextPutInt32MSB: anIntegerOrCharacter
do not remove.
See #patchByteOrderOptimizedMethods

o  nextPutInt32NATIVE: anInteger
Write the argument, anInteger as a long (four bytes) in native byte order.
This is the CPU-specific byte order (LSB on x86 and VAX, MSB on sparc and possibly on ARM).
Notice that integers in the range 16r-80000000 to +16rFFFFFFFF can be written
(i.e. both signed and unsigned int32 values can be written.
Works in both binary and text modes.
Notice: this message should not be sent explicitly by ANY program.
the following implementation replaces the code of either nextPutInt32MSB or LSB
dynamically (see #initialize on the class side)

o  nextPutUtf16: aCharacter
append my UTF-16 MSB representation to the argument, aStream.
UTF-16 can encode only characters with code points between 0 to 16r10FFFF.

Usage example(s):

	(FileStream newTemporary
	    nextPutUtf16:$B;
	    nextPutUtf16:$Ä;
	    nextPutUtf16:(Character codePoint:16r10CCCC);
	    reset;
	    binary;
	    contents)

o  nextPutUtf16: aCharacter MSB: msbFlag
append my UTF-16 MSB representation to the argument, aStream.
UTF-16 can encode only characters with code points between 0 to 16r10FFFF.

positioning
o  position
(comment from inherited method)
return the read position (0-based)

** This method must be redefined in concrete classes (subclassResponsibility) **

o  position: index0Based
(comment from inherited method)
redefined to allow positioning past the readLimit

** This method must be redefined in concrete classes (subclassResponsibility) **

o  skipBufferedData
skip (throw away) all data that is currently buffered in myself.
Answer the number of bytes that have been skipped, 0 if nothing was buffered.

printing & storing
o  printOn: aStream
(comment from inherited method)
'' readStream printString
'' writeStream printString

private
o  clearEOF

o  closeFile
low level close - may be redefined in subclasses
Don't send this message, send #close instead

o  closeFile: handle
for rel5 only

o  connectTo: aFileDescriptor withMode: modeSymbol handleType: handleTypeSymbol
connect a fileDescriptor; openmode is the string defining the way to open.
This can be used to connect an externally provided fileDescriptor (from
primitive code) or a pipeFileDescriptor (as returned by makePipe) to
a Stream object.
The openMode ('r', 'w' etc.) must match the mode in which
the fileDescriptor was originally opened (otherwise i/o errors will be reported later).

o  dupFd
duplicate my file descriptor

o  fopenMode
answer the mode for fopen.
Only used internally

o  open: aPathArg withMode: openModeString
low level open; opens the file/device and sets the handle instance
variable.
Careful: this does not care for any other state.
Also be careful: unless opened with 'b' in the modeString,
Windows will translate written CRs to CRNL;
usually this is NOT wanted; especially for binary files.

o  reOpen
USERS WILL NEVER INVOKE THIS METHOD
sent after snapin to reopen streams.
cannot reopen here since I am abstract and have no device knowledge

o  setAccessor: what to: something
set the filePointer/fileHandle to the given one;
low level private & friend interface; may also be used to connect to some
externally provided handle.

o  setFileHandle: something
set the fileHandle to the given one;
low level private & friend interface; may also be used to connect to some
externally provided file handle.

o  setFileHandle: anIntegerOrExternalAddress mode: openMode
set the handle based upon a given fileHandle -
notice: this one is based on the underlying OSs fileDescriptor -
this is a fileDescriptor (Integer) on Unix and Windows, or an Handle (ExternalAddres) on Windows only.
It may not be available on all platforms.

o  setFilePointer: something
set the filePointer to the given one;
low level private & friend interface; may also be used to connect to some
externally provided file.

o  setLastError: aNumber

o  setSocketHandle: something
set the socketHandle to the given one;
low level private & friend interface; may also be used to connect to some
externally provided socket handle.

queries
o  atEnd
return true, if position is at end.
If a stream is at the end, the next read operation
would return or raise an exception immediately without waiting.
If a stream is not at the end, this may be a blocking operation
(see NonPositionableExternalStream)

o  nextError
return the error by trying to read something.
Should only be used, when we know, that a read operation
will return an error (otherwise a character may be lost).
Return an integer (error number), 0 (EOF) or nil (no error)

o  numAvailable

** This is an obsolete interface - do not use it (it may vanish in future versions) **

reading
o  next
return the next element; advance read position.
In binary mode, an integer is returned, otherwise a character.
If there are no more elements, either an exception is thrown or nil is returned
- see #pastEndRead.

o  next: count
return the next count elements of the stream as a collection.
Redefined to return a String or ByteArray instead of the default: Array.

o  nextOrNil
return the next element; advance read position.
In binary mode, an integer is returned, otherwise a character.
If there are no more elements, nil is returned.
This is #atEnd and #next in a single operation - to speed up some code

o  peek
return the element to be read next without advancing read position.
In binary mode, an integer is returned, otherwise a character.
If there are no more elements, either an exception is thrown or nil is returned
- see #pastEndRead.

o  peekOrNil
return the element to be read next without advancing read position.
In binary mode, an integer is returned, otherwise a character.
If there are no more elements, nil is returned.
Same as #atEnd and #peek in a single operation - speeding up some code

o  peekOrNilNoWait
like #peek, this returns the next element, if available.
If nothing is available, this does never raise a read-beyond end signal.
Instead, nil is returned immediately.

It does not wait on pipes and sockets an returns only data, that is already present.
Redefined for NonPositionableExternalStream compatibility.

o  upToEnd
return a collection of the elements up-to the end.
Return an empty collection, if the stream is already at the end.

Usage example(s):

     '/dev/null' asFilename readStream upToEnd
     '/proc/self/stat' asFilename readStream upToEnd
     'librun.so' asFilename readStream binary upToEnd
     (PipeStream readingFrom:'tasklist /v') upToEnd

     self assert:('smalltalk.rc' asFilename readStream upToEnd size)
		  =  ('smalltalk.rc' asFilename readStream size)

rel5 protocol
o  atEndFile: handle
for migration to rel5 only

o  nextByteFromFile: handle
for migration to rel5 only

o  nextPutByte: aByte toFile: handle
for migration to rel5 only

testing
o  gotErrorOrEOF
answer true, if amn error or eof has been occurred on the stream

o  isBinary
return true, if the stream is in binary (as opposed to text-) mode.
The default when created is false.

o  isBlocking
return true, if O_NONBLOCK is NOT set in the fileDescriptor (probably UNIX specific)

o  isBuffered
return true, if writes to stream do not cause a system call for each operation.

o  isExecutor
am I an executor and no real stream object?

o  isExternalStream
return true, if the receiver is some kind of externalStream;
true is returned here - the method redefined from Object.

o  isOpen
return true, if this stream is open

Usage example(s):

executors are only used to finalize - they are not really open and are closed with #closeFile,
     which does not check for #isOpen

o  isPipeStream
return true, if this stream is a pipe

o  isReadable
return true, if this stream can be read from

o  isSerialPort
return false here; to be redefined in subclass(es)

o  isSocket
return true, if this stream is a socket

o  isTTYStream
return true, if this stream is a tty stream (UNIX)

Usage example(s):

     Stdout isTTYStream
     Stderr isTTYStream
     Stdin isTTYStream
     '/dev/null' asFilename readStream isTTYStream
     'makefile' asFilename readStream isTTYStream

o  isUnicodeEncoded
return true, if the streamed collection is any string (8-, 16- or 32-bit),
which definitly is not using UTF-x or JIS or any other encoding.
I.e. 'self next' always returns a unicode character.
ExternalStreams never return unicode characters.

o  isWritable
return true, if this stream can be written to

waiting for I/O
o  canBeSelected
return true, if this stream can be selected upon

o  numAvailableForRead
answer the number of bytes available for reading

Usage example(s):

	'/etc/hosts' asFilename readStream numAvailableForRead

o  readWaitWithTimeoutMs: timeoutOrNil
suspend the current process, until the receiver
becomes ready for reading or a timeout (in milliseconds) expired.
If timeoutOrNil is nil, wait without timeout.
If data is already available, return immediate.
Return true if a timeout occurred (i.e. false, if data is available).
The other threads are not affected by the wait.

o  readWriteWaitWithTimeoutMs: timeoutOrNil
suspend the current process, until the receiver
becomes ready for reading or writing or a timeout (in milliseconds) expired.
Return true if a timeout occurred (i.e. false, if data is available).
Return immediate if the receiver is already ready.
The other threads are not affected by the wait.

o  writeExceptionWaitWithTimeoutMs: timeoutOrNil
suspend the current process, until the receiver
becomes ready for writing or an exceptional event or a timeout (in milliseconds) expired.
Return true if a timeout occurred (i.e. false, if data is available).
Return immediate if the receiver is already ready.
The other threads are not affected by the wait.

o  writeWaitWithTimeoutMs: timeoutOrNil
suspend the current process, until the receiver
becomes ready for writing or a timeout (in milliseconds) expired.
Return true if a timeout occurred (i.e. false, if data is available).
Return immediate if the receiver is already ready.
The other threads are not affected by the wait.

writing
o  contents: aStringOrByteArrayOrCollectionOfLines
create (or overwrite) a file given its contents as a collection of lines.
Raises an error, if the file is unwritable.

Usage example(s):

     'foo1' asFilename writeStream
	    contents:#('one' 'two' 'three'); close.
     'foo2' asFilename writeStream
	    contents:'Hello world'; close.
     'foo3' asFilename writeStream
	    contents:#[1 2 3 4 5]; close.

     #(foo1 foo2 foo3) do:[:e | e asFilename remove].

o  cr
append an end-of-line character (or CRLF if in crlf mode).
reimplemented for speed

o  flush
write all buffered data

o  nextPut: aCharacter
write the argument, aCharacter - raise an error if failed.
Answer aCharacter.
Only single-byte characters are supported here

o  nextPutAll: aCollection
write all elements of the argument, aCollection.
Answer the receiver.
Reimplemented for speed when writing strings or byteArrays.
For others, falls back to general method in superclass.

o  nextPutAll: initialWriteCount from: buffer startingAt: initialOffset
append count elements with index starting at initialOffset
of the argument, buffer onto the receiver.
This is only allowed, if the receiver supports writing.
Answer the number of elements that were appended.
Buffer should be a byte collection.
I don't know how to write non-bytes to an external stream, but let superclass handle this.

o  nextPutAll: aCollection startingAt: start to: stop
write a range of elements of the argument, aCollection.
Reimplemented for speed when writing strings or byteArrays.
For others, falls back to general method in superclass.

o  nextPutAllUnicode: aString
normal streams can not handle multi-byte characters, so convert them to utf8.
This is needed, so that you can do ('something' asUnicode16String errorPrintCR)

o  nextPutBytes: count from: anObject startingAt: start
write count bytes from an object starting at index start.
return the number of bytes written - which could be 0.
The object must have non-pointer indexed instvars
(i.e. be a ByteArray, String, Float- or DoubleArray),
or an externalBytes object (with known size).

Use with care - non object oriented i/o.
Warning:
in general, you cannot use this method to pass non-byte data to other
architectures (unless you prepared the buffer with care),
since it does not care for byte order or float representation.

o  nextPutUnicode: aCharacter
normal streams can not handle multi-byte characters, so convert them to utf8


Examples:


open a file, read the contents and display it in a textView:
    |topView scrollPane textView fileStream text|

    topView := StandardSystemView new.
    topView label:'contents of Makefile'.

    scrollPane := HVScrollableView in:topView.
    scrollPane origin:0.0@0.0 corner:1.0@1.0.

    textView := EditTextView new.
    scrollPane scrolledView:textView.

    fileStream := 'Makefile' asFilename readStream.
    text := fileStream upToEnd.
    fileStream close.

    textView contents:text.

    topView open.
Notice, all of the above can also be done (simply) as:
    EditTextView openOn:'Makefile'


ST/X 7.7.0.0; WebServer 1.702 at 20f6060372b9.unknown:8081; Thu, 21 Nov 2024 11:08:56 GMT