This code is the declaration and definition of the TextFileIterator class which is an indirect subclass of the Iterator class. Other than minor formatting for HTML presentation, this code is exactly as found in the production source code.
// Copyright (c) 1993..1996 by Michael Lee Finney. All rights reserved.
#pragma pack(4)
/* TextFileIterator
*
* Instances of TextFileIterator iterate over the characters in a
* text file of 8-bit characters which are converted to Unicode by
* the iterator. The position of the iterator does not correspond
* exactly (because of end of line translation) to a byte index into
* the text file. Therefore, the iterator cannot be positioned to
* any location other than the start of the text file, the current
* character and the next character.
*
* Note: Currently, it is assumed that the 8-bit characters are codepoints
* in the ISO 8859-1 which is a strict subset of 16-bit Unicode.
*/
class TextFileIterator isa UnicharIterator is
SubClassMethods(TextFileIterator, UnicharIterator);
private:
protected:
InputFileDoubleBufferIterator _buffers; // Input FileBuffer iterator
char * _ptr; // Pointer to next character in file buffer
char * _end; // Pointer to end of data in file buffer
unsigned4 _position; // Position into file
unsigned4 _lines; // Number of lines detected on look-ahead
unichar _char; // Current character
bool _atEnd; // End of file reached
virtual void readNextBuffer();
public:
virtual bool isComparable(Order const & x) const;
virtual signed4 origin() const;
virtual signed4 position() const;
virtual bool atLowerBound() const;
virtual bool atUpperBound() const;
virtual bool isAccessibleAt(signed4 aPosition) const;
virtual void moveTo(signed4 aPosition);
virtual bool isAccessible(signed4 i) const;
virtual void move(signed4 i);
virtual void advance();
virtual bool isResettable() const;
virtual void reset();
virtual bool isValueAt(signed4 aPosition) const;
virtual unichar const & valueAt(signed4 aPosition) const;
virtual bool isValue(signed4 i) const;
virtual unichar const & value(signed4 i) const;
virtual bool isValue() const;
virtual unichar const & value() const;
virtual Iterator<unichar> const & operator=(Iterator<unichar> const & anIterator);
TextFileIterator(char const * fileName, unsigned4 bufferLength = 4096);
TextFileIterator(TextFileIterator const & iterator);
virtual ~TextFileIterator();
global
IteratorOperatorSignatures(TextFileIterator);
#pragma pack()
/* TextFileIterator::origin
*
* Return r (the iterator origin). This is the position the iterator
* has immediately following creation or the reset() operation.
*/
inline signed4 TextFileIterator::origin() const is
code
nil;
end (1)
/* TextFileIterator::position
*
* Return p (the distinguished position).
*/
inline signed4 TextFileIterator::position() const is
code
nil;
end (_position)
/* TextFileIterator::atLowerBound
*
* Returns true iff p = L, i.e. the distinguished position is at
* the greatest lower bound of the indexing set.
*/
inline bool TextFileIterator::atLowerBound() const is
code
nil;
end (_position < 1)
/* TextFileIterator::atUpperBound
*
* Returns true iff p == U, i.e. the distinguished position is at
* the least upper bound of the indexing set.
*/
inline bool TextFileIterator::atUpperBound() const is
code
nil;
end (_atEnd)
/* TextFileIterator::isAccessibleAt
*
* Return true iff the specified position is accessible (i.e. in A).
*/
inline bool TextFileIterator::isAccessibleAt(
signed4 aPosition) const is
code
nil;
end ((not _atEnd and aPosition == _position + 1) or aPosition == 1 or _position == aPosition)
/* TextFileIterator::isAccessible
*
* Return true iff the specified position is accessible (i.e. in A).
*/
inline bool TextFileIterator::isAccessible(
signed4 i) const is
code
nil;
end ((not _atEnd and i == 1) or _position + i == 1 or i == 0)
/* TextFileIterator::isResettable
*
* Returns true iff the iterator can be reset so that it is
* in the same state as existed immediately following creation.
*/
inline bool TextFileIterator::isResettable() const is
code
nil;
end (true)
/* TextFileIterator::isValueAt
*
* Returns true iff the specified position in M, i.e. is defined.
*/
inline bool TextFileIterator::isValueAt(
signed4 aPosition) const is
code
nil;
end (not _atEnd and aPosition == _position)
/* TextFileIterator::valueAt
*
* Returns m(i), i.e. the value of the iterator at the specified
* position.
*/
inline unichar const & TextFileIterator::valueAt(
signed4 aPosition) const is
require
when (_atEnd or aPosition != _position)
reject ("Attempted to access iterator at an undefined position");
proc
nil;
end (_char)
/* TextFileIterator::isValue
*
* Returns true iff p+i is defined, i.e. in M.
*/
inline bool TextFileIterator::isValue(
signed4 i) const is
code
nil;
end (not _atEnd and i == 0)
/* TextFileIterator::value
*
* Returns m(p+i).
*/
inline unichar const & TextFileIterator::value(
signed4 i) const is
require
when (_atEnd or i)
reject ("Attempted to access iterator at an undefined position");
proc
nil;
end (_char)
/* TextFileIterator::isValue
*
* Returns true iff the distinguished position is defined, i.e. in M.
* The distinguished position is always defined except when p = L or
* p = U (which is only possible for finite iterators).
*/
inline bool TextFileIterator::isValue() const is
code
nil;
end (not _atEnd)
/* TextFileIterator::value
*
* Returns m(p), the value of the iterator at the distinguished
* position.
*/
inline unichar const & TextFileIterator::value() const is
code
nil;
end (_char)
/* TextFileIterator::readNextBuffer
*
* Read data from the file into _buffer.
*/
void TextFileIterator::readNextBuffer() is
code
_buffers.advance();
_ptr = (char *)_buffers.value().bufferStart();
_end = (char *)_buffers.value().bufferEnd();
if (_buffers.isAccessible(2))
*_end = 0x01;
else
*_end = 0x1a;
end (nil)
/* TextFileIterator::isComparable
*
* This method returns true iff the left object and the right object
* are comparable.
*/
bool TextFileIterator::isComparable(
Order const & x) const is
local
bool result;
code
#if (_rttiEnabled)
result = (typeId(x) == classId(TextFileIterator)) and
(_buffers.isComparable(((TextFileIterator const &)x)._buffers));
#else
result = true;
#endif
end (result)
/* TextFileIterator::moveTo
*
* Move the distinguished position to the specified position.
*/
void TextFileIterator::moveTo(
signed4 newPosition) is
code
if (newPosition == _position)
nil;
elif (newPosition == 1)
reset();
elif (not _atEnd and newPosition == _position + 1)
advance();
else
reject ("Attempt to position iterator to inaccessible position");
end (nil)
/* TextFileIterator::move
*
* Move the distinguished position by the specified amount.
*/
void TextFileIterator::move(
signed4 i) is
code
if (i == 0)
nil;
elif (_position + i == 1)
reset();
elif (not _atEnd and i == 1)
advance();
else
reject ("Attempt to position iterator to inaccessible position");
end (nil)
/* TextFileIterator::advance
*
* Advances the distinguished position to the next position.
*/
void TextFileIterator::advance() is
local
char c;
require
when (_atEnd)
reject ("Attempt to position iterator to inaccessible position");
proc
if (_lines)
{
--_lines;
if (_lines == 0 and *_ptr == 0x1a)
_atEnd = true;
else
_char = uniLineSeparator;
}
else
loop
{
c = *_ptr;
++_ptr;
if (c >= ' ' or c == tab)
_char = c; // Note: Convert to Unicode based on current code page.
elif (c == cr)
{
loop
{
when (*_ptr == 0x01 and _ptr == _end)
readNextBuffer();
if (*_ptr == cr)
++_lines;
else
upon (*_ptr == nul);
++_ptr;
}
when (*_ptr == lf)
{
++_ptr;
when (*_ptr == 0x01 and _ptr == _end)
readNextBuffer();
_lines = 0;
}
while (*_ptr == ff or *_ptr == nul)
{
++_ptr;
when (*_ptr == 0x01 and _ptr == _end)
readNextBuffer();
}
if (_lines == 0 and *_ptr == 0x1a)
_atEnd = true;
else
_char = uniLineSeparator;
}
elif (c == lf)
{
loop
{
when (*_ptr == 0x01 and _ptr == _end)
readNextBuffer();
upon (*_ptr == cr or *_ptr == nul);
++_ptr;
}
while (*_ptr == ff or *_ptr == nul)
{
++_ptr;
when (*_ptr == 0x01 and _ptr == _end)
readNextBuffer();
}
if (*_ptr == 0x1a)
_atEnd = true;
else
_char = uniLineSeparator;
}
elif (c == ff)
{
loop
{
when (*_ptr == 0x01 and _ptr == _end)
readNextBuffer();
upon (*_ptr == ff or *_ptr == nul);
++_ptr;
}
if (*_ptr == cr or *_ptr == lf)
continue;
elif (*_ptr == 0x1a)
_atEnd = true;
else
_char = uniLineSeparator;
}
elif (c == nul)
{
loop
{
when (*_ptr == 0x01 and _ptr == _end)
readNextBuffer();
upon (*_ptr == nul);
++_ptr;
}
continue;
}
elif (c == 0x1a)
_atEnd = true;
elif (c == 0x01 and _ptr > _end)
{
readNextBuffer();
continue;
}
else
_char = c; // Note: Convert to Unicode based on current code page.
break;
}
++_position;
end (nil)
/* TextFileIterator::reset
*
* Resets the iterator so that it is in the same state as existed
* immediately following creation. Following reset(), the atOrigin()
* method will be true and position() == origin().
*/
void TextFileIterator::reset() is
code
_buffers.reset();
if (_buffers.atUpperBound())
{
_atEnd = true;
_position = 1;
}
else
{
_ptr = (char *)_buffers.value().bufferStart();
_end = (char *)_buffers.value().bufferEnd();
_atEnd = false;
_position = 0;
if (_buffers.isAccessible(2))
*_end = 0x01;
else
*_end = 0x1a;
advance();
}
end (nil)
/* TextFileIterator::operator=
*
* Assignment.
*/
Iterator<unichar> const & TextFileIterator::operator=(
Iterator<unichar> const & anIterator) is
local
TextFileIterator const & iterator = (TextFileIterator const &)anIterator;
code
unless (self == &iterator)
{
_buffers = iterator._buffers;
_position = iterator._position;
_lines = iterator._lines;
_char = iterator._char;
_atEnd = iterator._atEnd;
if (_atEnd)
{
_ptr = null;
_end = null;
}
else
{
_ptr = (char *)_buffers.value().bufferStart() + (iterator._ptr - (char *)iterator._buffers.value().bufferStart());
_end = (char *)_buffers.value().bufferEnd();
}
}
end (*self)
/* TextFileIterator::TextFileIterator
*
* Constructor.
*/
TextFileIterator::TextFileIterator(
char const * fileName,
unsigned4 bufferLength)
constructors
_buffers(fileName, bufferLength, 1) is
code
_lines = 0;
if (_buffers.atUpperBound())
{
_position = 1;
_atEnd = true;
_ptr = null;
_end = null;
}
else
{
_ptr = (char *)_buffers.value().bufferStart();
_end = (char *)_buffers.value().bufferEnd();
if (_buffers.isAccessible(2))
*_end = 0x01;
else
*_end = 0x1a;
_position = 0;
_atEnd = false;
advance();
}
end (nil)
/* TextFileIterator::TextFileIterator
*
* Copy constructor.
*/
TextFileIterator::TextFileIterator(
TextFileIterator const & iterator)
constructors
_buffers(iterator._buffers) is
code
_position = iterator._position;
_lines = iterator._lines;
_char = iterator._char;
_atEnd = iterator._atEnd;
if (_atEnd)
{
_ptr = null;
_end = null;
}
else
{
_ptr = (char *)_buffers.value().bufferStart() + (iterator._ptr - (char *)iterator._buffers.value().bufferStart());
_end = (char *)_buffers.value().bufferEnd();
}
end (nil)
/* TextFileIterator::~TextFileIterator
*
* Virtual destructor.
*/
TextFileIterator::~TextFileIterator() is
code
nil;
end (nil)
/* IteratorOperatorSignatures
*
* Define the operators for the TextFileIterator class.
*/
IteratorOperators(TextFileIterator)