Class AStream

DescriptionHierarchyFieldsMethodsProperties

Unit

Declaration

type AStream = class(AnObject, CanIterate)

Description

The base stream type.

This class represents a basic binary stream that supports reading, writing, and random access. The class defines several abstract methods which its descendants are expected to implement:

as well as several utility routines.

Because this class represents an abstract stream, it is not meant to be directly instantiated; instead, you will use one of its descendants. To write to a disk-based file, you will use AFileOutputStream or one of its descendants. To read from a disk-based file, you will use AFileInputStream or one of its descendants. To read and write from a memory-based stream, you can use AStringStream or one of its descendants.

All streams are expected to implement the CanIterate interface. This class provides a default implementation, which returns an instance of AStreamIterator. AStream itself uses this interface to implement AStream.checksum, as shown here:


  // Calculate a checksum for the stream
  function AStream.checksum: TStreamChecksum;

  var
    // Stores the size of the stream
    streamSize: TStreamLength;
    // Stores the position in the stream before the checksum was calculated
    previousPosition: TStreamOffset;
    // Used to iterate over the stream
    Element: AStreamIterator;

  begin
    result := 0;
    streamSize := Self.length;
    if streamSize > 0 then
    begin
      // Store the current position
      previousPosition := Self.position;

      Element := AStreamIterator(Self.iterator);
      result := crc64(0, nil, 0);

      while Element.continues do
      begin
        result := crc64(result, Element.value, Element.size);
        Element.next;
      end;

      Element.free;
      // Seek the previous position
      Self.setPosition(previousPosition);
    end;
  end;
  

Hierarchy

Overview

Methods

Public function read(const count: TStreamIOSize; var dest): TStreamIOSize; virtual; abstract;
Public function write(const count: TStreamIOSize; const source): TStreamIOSize; virtual; abstract;
Public function writeEach(const vals: array of const): TStreamIOSize; virtual;
Public function writeString(const str: AnsiString): TStreamIOSize; virtual;
Public function readString(var str: AnsiString): TStreamIOSize; virtual;
Public function rewindBy(count: TStreamIOSize): TStreamOffset; virtual;
Public function checksum: TStreamChecksum; virtual;
Public function iterator: AnIterator; virtual;
Public function position: TStreamOffset; virtual; abstract;
Public function setPosition(newPosition: TStreamOffset): TStreamOffset; virtual; abstract;
Public function length: TStreamLength; virtual; abstract;
Public function hasEnded: boolean; virtual;

Description

Methods

Public function read(const count: TStreamIOSize; var dest): TStreamIOSize; virtual; abstract;

Read count bytes from the stream and store the data in dest.

This method is to be implemented by descendant classes. It should obtain the desired amount of data, if possible, and store it in the memory specified by dest.

This method may throw an exception if the read fails, but it should NOT throw an exception if the end of the stream is encountered; instead, it should simply return the total number of bytes that were read before the end of the stream was reached.

It is the caller's responsibility to ensure that dest has at least count bytes available for storage; failure to do so will likely cause your program to crash.

Returns

The total number of bytes read from the stream. This value may be less than count if the end of the stream was encountered while reading.

Public function write(const count: TStreamIOSize; const source): TStreamIOSize; virtual; abstract;

Write count bytes of source to the stream.

This method is to be implemented by descendant classes. It should read the desired amount of data from source and output it to the stream.

This method may throw an exception if the write fails.

It is the caller's responsibility to ensure that source has at least count bytes ready to be written; failure to do so will likely cause your code to crash.

Returns

The total number of bytes written to the stream.

Public function writeEach(const vals: array of const): TStreamIOSize; virtual;

Write each value in vals to the stream.

This method is defined and implemented as a convenience function; it writes each variable provided in vals to the stream by calling AStream.write on each. The type information encoded by the compiler is used to determine the size of each value to write. The values are written as-is, in binary form, making this method unsuitable for printing text output.

It is possible to pass instances of objects to this routine, but they must be members of a class that implements CanStream. This routine will call the writeTo method for all such instances passed. All other object instances passed to this routine are ignored.

If a class reference is passed to this routine, it will output a string containing the name of the class.

Returns

The total number of bytes written to the stream. This value may be less than expected if certain items in vals were skipped.

Public function writeString(const str: AnsiString): TStreamIOSize; virtual;

Write a string to the stream.

This method first writes the length specifier of str, then writes a checksum for that length before writing the text of str itself.

The checksum is written as a precaution, to help ensure that an invalid string can be detected when reading from the stream before an attempt is made to read it. This can prevent memory errors, since otherwise it would be possible to position the stream at an arbitrary location and attempt to read a string, with undefined results. The checksum written is simply the negative value of the string's length. For instance, if str is 255 bytes in length, the checksum written will be -255.

The string written by this routine can be recalled from the stream by calling AStream.readString.

Note: The length specifier and checksum written will always be of type TStreamIOSize (currently unsigned 32-bit integer values).

Because it writes the binary value of the length specifier to the stream, this method is not suitable for simply printing a string for display to an end-user.

Returns

The total number of bytes printed to the stream. This value should be the length of str plus the length of its length specifier and checksum.

Public function readString(var str: AnsiString): TStreamIOSize; virtual;

Read a string from the stream.

This method first reads the length specifier and checksum from the stream. If the negative value of the checksum matches that of the length specifier, then the text of the string itself is read from the stream; if not, then this routine will set str to an empty string and exit.

Note: The length specifier and checksum read will always be of type TStreamIOSize (currently unsigned 32-bit integer values).

Returns

The total number of bytes read from the stream. This value should be the length of the string, plus the length of its length specifier and checksum. In the event that the checksum and length specifier do not match as described above, the value returned by this routine will be exactly the size of the checksum and length specifier (currently 8 bytes).

Public function rewindBy(count: TStreamIOSize): TStreamOffset; virtual;

Rewinds the stream position pointer by count bytes. Subsequent reads from or writes to the stream will occur at the new position.

This method is useful when it is necessary to read from the stream and then ensure that the same data is read again.

The absolute value of count is used. If count represents a value that is greater than the current offset within the stream (in other words, if the stream position pointer would end up as a negative number) then the stream position pointer is reset to the beginning of the stream.

Returns

The previous position within the stream, as an offset in bytes from the beginning of the stream.

Public function checksum: TStreamChecksum; virtual;

Calculate a 64-bit CRC checksum for the stream.

The base implementation of this method starts at the current position within the stream and iterates over all bytes encountered until the end of the stream. It then returns the stream position pointer to where it was when the method was called, and returns the checksum calculated.

The reason the method starts at the current position within the stream, instead of at the beginning of the stream, is to allow for a stream header that will contain the calculated checksum. Since the checksum value in the stream header is undefined, it should not be included in the checksum calculation, or subsequent attempts to verify the stream against the checksum will fail.

Descendant classes may override this method to introduce different behavior.

Returns

The 64-bit CRC checksum for the stream.

Public function iterator: AnIterator; virtual;

Construct and return an iterator suitable for processing the stream.

The iterator returned by the base implementation of this routine will be an instance of AStreamIterator, which allows access to the individual bytes that make up the stream. Descendant classes may override this method to return a different iterator type.

Public function position: TStreamOffset; virtual; abstract;

Return the current position within the stream.

This method should be implemented by descendant classes. It should return the value of the stream position pointer, which indicates where the next read or write operation will take place, as an offset in bytes from the beginning of the stream. The beginning of the stream should always be represented as offset zero (0).

Public function setPosition(newPosition: TStreamOffset): TStreamOffset; virtual; abstract;

Set the current position within the stream.

This method should be implemented by descendant classes. It should set the stream position pointer to newPosition and return the previous value of the position pointer.

newPosition may be a positive or negative value. If positive, it represents an offset in bytes from the beginning of the stream, where offset zero (0) represents the beginning of the stream. If newPosition is a negative value, it represents an offset in bytes from the end of the stream, where offset -1 represents the end of the stream.

This method should not throw an exception if the underlying mechanism does not support repositioning; it should instead fail silently and return the current, unchanged position within the stream.

Public function length: TStreamLength; virtual; abstract;

Retrieve the current length of the stream.

This method should be implemented by descendant classes. It must return the current size of the stream, in bytes.

Public function hasEnded: boolean; virtual;

Determine whether or not the end of the stream has been reached.

The base implementation of this method simply checks to see whether AStream.position is greater than or equal to AStream.length; if so, it returns True. Descendant classes may override this method in order to take advantage of another mechanism instead.

Returns

True if the end of the stream has been reached; False if not.


Generated by PasDoc 0.13.0 on 2015-01-10 17:13:18