Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

ExternalStream.cc

Go to the documentation of this file.
00001 /*
00002  * ExternalStream.cc
00003  *
00004  * Smalltalk like class library for C++
00005  * Abstract external stream.
00006  *
00007  * Copyright (c) 2003 Milan Cermak
00008  */
00009 /*
00010  * This library is free software; you can redistribute it and/or
00011  * modify it under the terms of the GNU Lesser General Public
00012  * License as published by the Free Software Foundation; either
00013  * version 2.1 of the License, or (at your option) any later version.
00014  *
00015  * This library is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018  * Lesser General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU Lesser General Public
00021  * License along with this library; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023  */
00024 #include <stlib/ExternalStream.h>
00025 
00026 #include <stlib/ByteArray.h>
00027 #include <stlib/Character.h>
00028 #include <stlib/IOAccessor.h>
00029 #include <stlib/IOBuffer.h>
00030 #include <stlib/SequenceableCollection.h>
00031 #include <stlib/String.h>
00032 #include <stlib/WriteStream.h>
00033 #include <stlib/Error.h>
00034 
00035 ExternalStream::ExternalStream(IOAccessor *accessor)
00036 {
00037     io_accessor = accessor;
00038     io_buffer = new IOBuffer(io_accessor);
00039     PositionableStream::initialize(io_buffer->buffer());
00040     _position = io_buffer->firstDataPosition();
00041     read_limit = 0;
00042     write_limit = -1;
00043 }
00044 
00045 /* Class-accessing protocol */
00046 String *ExternalStream::className(void) const
00047 {
00048     return new String("ExternalStream");
00049 }
00050 
00051 /* Accessing protocol */
00052 SequenceableCollection *ExternalStream::contents(void)
00053 {
00054     long dataSize;
00055     Stream *newCollectionStream;
00056 
00057     dataSize = io_accessor->dataSize();
00058     newCollectionStream = contentSpeciesFor(dataSize < 256 ? 256 : dataSize)
00059                               ->writeStream();
00060     while (!atEnd()) {
00061         newCollectionStream->nextPut(next());
00062     }
00063     return newCollectionStream->contents();
00064 }
00065 
00066 /* Positioning protocol */
00067 long ExternalStream::readPosition(void)
00068 {
00069     // openIfClosed();
00070     return io_buffer->currentBufferPosition() + _position;
00071 }
00072 
00073 /* Status protocol */
00074 void ExternalStream::close(void)
00075 {
00076     if (!closed()) {
00077         closeConnection();
00078         io_buffer = nil;
00079         collection = contentSpeciesFor(0);
00080     }
00081 }
00082 
00083 bool ExternalStream::closed(void)
00084 {
00085     return io_buffer == nil;
00086 }
00087 
00088 void ExternalStream::commit(void)
00089 {
00090     io_buffer->commit();
00091 }
00092 
00093 /* Testing protocol */
00094 bool ExternalStream::atEnd(void)
00095 {
00096     if (!basicAtEnd()) return false;
00097     if (!nextBuffer()) return true;
00098     return _position == read_limit;
00099 }
00100 
00101 bool ExternalStream::isBinary(void)
00102 {
00103     return true;
00104 }
00105 
00106 bool ExternalStream::isExternalStream(void)
00107 {
00108     return true;
00109 }
00110 
00111 /* Private protocol */
00112 void ExternalStream::closeConnection(void)
00113 {
00114     try {
00115         flush();
00116         io_accessor->close();
00117         _position = read_limit = 0;
00118         write_limit = -1;
00119     }
00120     catch (Error *ex) {
00121         /* Do nothing */
00122     }
00123 }
00124 
00125 bool ExternalStream::nextBuffer(void)
00126 {
00127     long offset;
00128 
00129     flush();
00130     collection = io_buffer->nextAndSetOffset(offset);
00131     _position = offset;
00132     read_limit = io_buffer->lastDataPosition();
00133     return read_limit > _position;
00134 }
00135 
00136 Object *ExternalStream::pastEnd(void)
00137 {
00138     // openIfClosed();
00139     if (_position < read_limit)
00140         return collection->at(_position++);
00141     if (nextBuffer())
00142         return collection->at(_position++);
00143     /* End of stream. Must be signaled somehow. */
00144     return nil;
00145 }
00146 
00147 void ExternalStream::setPosition(long index)
00148 {
00149     long offset;
00150 
00151     if (index < 0) {
00152         Error *ex = new Error(new String("Attempt to position to a negative number."),
00153                               new String(__PRETTY_FUNCTION__));
00154         ex->raiseFrom(this);
00155     }
00156     flush();
00157     collection = io_buffer->readPositionAndSetOffset(index, offset);
00158     _position = offset;
00159     read_limit = io_buffer->lastDataPosition();
00160 }

Generated on Mon Nov 27 09:47:55 2006 for Smalltalk like C++ Class Library by  doxygen 1.4.2