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

Stream.cc

Go to the documentation of this file.
00001 /*
00002  * Stream.cc
00003  *
00004  * Smalltalk like class library for C++
00005  * Abstract stream.
00006  *
00007  * Copyright (c) 2003-6 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/Stream.h>
00025 #include <stlib/WriteStream.h>
00026 
00027 #include <stlib/Array.h>
00028 #include <stlib/ByteArray.h>
00029 #include <stlib/Character.h>
00030 #include <stlib/Collection.h>
00031 #include <stlib/Integer.h>
00032 #include <stlib/Iterator.h>
00033 #include <stlib/Number.h>
00034 #include <stlib/SequenceableCollection.h>
00035 #include <stlib/String.h>
00036 
00037 #include <stlib/POOBoundsError.h>
00038 
00039 /* Accessing protocol */
00040 Stream *Stream::basicStream(void)
00041 {
00042     return this;
00043 }
00044 
00045 SequenceableCollection *Stream::next(long items)
00046 {
00047     SequenceableCollection *newCollection;
00048     newCollection = contentSpeciesFor(items);
00049     return next(items, newCollection, 0);
00050 }
00051 
00052 SequenceableCollection *Stream::next(long items, SequenceableCollection *newColl, long index)
00053 {
00054     long stopIndex = index + items;
00055 
00056     while (index < stopIndex) {
00057         newColl->put(index, next());
00058         index++;
00059     }
00060     return newColl;
00061 }
00062 
00063 SequenceableCollection *Stream::nextLine(void)
00064 {
00065     return upTo(Character::lf());
00066 }
00067 
00068 Integer *Stream::nextBigEndianLong(void)
00069 {
00070     unsigned long number = 0;
00071     ByteArray *array = dynamic_cast<ByteArray *>(next(4));
00072 
00073     for (int i = 0; i < 4; i++) {
00074         number = (number << 8) + dynamic_cast<Integer *>(array->at(i))->asLong();
00075     }
00076 
00077     return Integer::value(number);
00078 }
00079 
00080 Integer *Stream::nextBigEndianShort(void)
00081 {
00082     unsigned long number = 0;
00083     ByteArray *array = dynamic_cast<ByteArray *>(next(2));
00084 
00085     for (int i = 0; i < 2; i++) {
00086         number = (number << 8) + dynamic_cast<Integer *>(array->at(i))->asLong();
00087     }
00088 
00089     return Integer::value(number);
00090 }
00091 
00092 Integer *Stream::nextLittleEndianLong(void)
00093 {
00094     unsigned long number = 0;
00095     ByteArray *array = dynamic_cast<ByteArray *>(next(4));
00096 
00097     for (int i = 3; i >= 0; i--) {
00098         number = (number << 8) + dynamic_cast<Integer *>(array->at(i))->asLong();
00099     }
00100 
00101     return Integer::value(number);
00102 }
00103 
00104 Integer *Stream::nextLittleEndianShort(void)
00105 {
00106     unsigned long number = 0;
00107     ByteArray *array = dynamic_cast<ByteArray *>(next(2));
00108 
00109     for (int i = 1; i >= 0; i--) {
00110         number = (number << 8) + dynamic_cast<Integer *>(array->at(i))->asLong();
00111     }
00112 
00113     return Integer::value(number);
00114 }
00115 
00116 void Stream::nextPut(const char object)
00117 {
00118     nextPut(Character::value((unsigned char) object));
00119 }
00120 
00121 void Stream::nextPutAll(const Collection *collection)
00122 {
00123     if (collection->isSequenceable()) {
00124         nextPutAll((SequenceableCollection *) collection,
00125                    collection->size(), 0L);
00126     } else {
00127         for (Iterator *i = collection->iterator(); !i->finished(); i->next()) {
00128             nextPut(i->value());
00129         }
00130     }
00131 }
00132 
00133 void Stream::nextPutAll(const char *string)
00134 {
00135     for (const char *pstr = string; *pstr != 0; pstr++) {
00136         nextPut(*pstr);
00137     }
00138 }
00139 
00140 void Stream::nextPutAll(const SequenceableCollection *collection,
00141                         long size, long startIndex)
00142 {
00143     for (long i = startIndex; i < startIndex + size; i++) {
00144         nextPut(collection->at(i));
00145     }
00146 }
00147 
00148 void Stream::nextPutBigEndianLong(Integer *number)
00149 {
00150     nextPutBigEndianLong(number->asUnsignedLong());
00151 }
00152 
00153 void Stream::nextPutBigEndianLong(unsigned long int number)
00154 {
00155     unsigned long particle = number;
00156     ByteArray *ba = new ByteArray(4);
00157     for (int i = 3; i >= 0; i--) {
00158         ba->put(i, Integer::value(particle & 0xff));
00159         particle = particle >> 8;
00160     }
00161     nextPutAll(ba);
00162 }
00163 
00164 void Stream::nextPutBigEndianShort(Integer *number)
00165 {
00166     nextPutBigEndianShort((unsigned short) number->asUnsignedLong());
00167 }
00168 
00169 void Stream::nextPutBigEndianShort(unsigned short int number)
00170 {
00171     unsigned short particle = number;
00172     ByteArray *ba = new ByteArray(2);
00173     for (int i = 1; i >= 0; i--) {
00174         ba->put(i, Integer::value(particle & 0xff));
00175         particle = particle >> 8;
00176     }
00177     nextPutAll(ba);
00178 }
00179 
00180 void Stream::nextPutLittleEndianLong(Integer *number)
00181 {
00182     nextPutLittleEndianLong(number->asUnsignedLong());
00183 }
00184 
00185 void Stream::nextPutLittleEndianLong(unsigned long int number)
00186 {
00187     unsigned long particle = number;
00188     ByteArray *ba = new ByteArray(4);
00189     for (int i = 0; i < 4; i++) {
00190         ba->put(i, Integer::value(particle & 0xff));
00191         particle = particle >> 8;
00192     }
00193     nextPutAll(ba);
00194 }
00195 
00196 void Stream::nextPutLittleEndianShort(Integer *number)
00197 {
00198     nextPutLittleEndianShort((unsigned short) number->asUnsignedLong());
00199 }
00200 
00201 void Stream::nextPutLittleEndianShort(unsigned short int number)
00202 {
00203     unsigned short particle = number;
00204     ByteArray *ba = new ByteArray(2);
00205     for (int i = 0; i < 2; i++) {
00206         ba->put(i, Integer::value(particle & 0xff));
00207         particle = particle >> 8;
00208     }
00209     nextPutAll(ba);
00210 }
00211 
00212 SequenceableCollection *Stream::upTo(Object *object)
00213 {
00214     Stream *newStream = contentSpeciesFor(64)->writeStream();
00215     while (!atEnd()) {
00216         Object *element = next();
00217         if (element->isEqual(object))
00218             break;
00219         newStream->nextPut(element);
00220     }
00221     return newStream->contents();
00222 }
00223 
00224 SequenceableCollection *Stream::upToAll(SequenceableCollection *sequence)
00225 {
00226     int matchCount = 0;
00227     Stream *writeStream = contentSpeciesFor(64)->writeStream();
00228     while (!atEnd()) {
00229         Object *element = next();
00230         if (element->isEqual(sequence->at(matchCount))) {
00231             matchCount++;
00232             if (matchCount == sequence->size()) break;
00233         } else {
00234             if (matchCount > 0) {
00235                 writeStream->nextPutAll(dynamic_cast<SequenceableCollection *>(sequence->copy(0, matchCount)));
00236                 matchCount = 0;
00237             }
00238             writeStream->nextPut(element);
00239         }
00240     }
00241     return writeStream->contents();
00242 }
00243 
00244 SequenceableCollection *Stream::upToAny(Collection *collection)
00245 {
00246     Stream *newStream = contentSpeciesFor(64)->writeStream();
00247     while (!atEnd()) {
00248         Object *element = next();
00249         if (collection->includes(element))
00250             break;
00251         newStream->nextPut(element);
00252     }
00253     return newStream->contents();
00254 }
00255 
00256 SequenceableCollection *Stream::upToEnd(void)
00257 {
00258     Stream *newCollectionStream = contentSpeciesFor(256)->writeStream();
00259     while (!atEnd()) {
00260         newCollectionStream->nextPut(next());
00261     }
00262     return newCollectionStream->contents();
00263 }
00264 
00265 SequenceableCollection *Stream::upToSeparator(void)
00266 {
00267     Stream *newStream = contentSpeciesFor(64)->writeStream();
00268     while (!atEnd()) {
00269         Object *element = next();
00270         if (element->isCharacter() &&
00271             ((Character *) element)->isSeparator())
00272             break;
00273         newStream->nextPut(element);
00274     }
00275     return newStream->contents();
00276 }
00277 
00278 Object *Stream::peek(void)
00279 {
00280     if (atEnd()) return nil;
00281     Object *element = next();
00282     skip(-1);
00283     return element;
00284 }
00285 
00286 /* Character reading protocol */
00287 void Stream::skipSeparators(void)
00288 {
00289     Object *element;
00290     bool atEndFlag;
00291 
00292     while (!(atEndFlag = atEnd()) &&
00293        (element = next())->isCharacter() &&
00294        ((Character *) element)->isSeparator());
00295     /* Cannot use atEnd() here because of ExternalReadStream
00296        buffer swap side effect */
00297     if (!atEndFlag) skip(-1);
00298 }
00299 
00300 /* Character writing protocol */
00301 void Stream::cr(void)
00302 {
00303     nextPut(Character::cr());
00304 }
00305 
00306 void Stream::lf(void)
00307 {
00308     nextPut(Character::lf());
00309 }
00310 
00311 void Stream::space(void)
00312 {
00313     nextPut(Character::space());
00314 }
00315 
00316 void Stream::tab(void)
00317 {
00318     nextPut(Character::tab());
00319 }
00320 
00321 /* Error handling protocol */
00322 void Stream::positionOutOfBoundsError(String *selector, int position)
00323 {
00324     (new PositionOutOfBoundsError(selector, position))->raiseFrom(this);
00325 }
00326 
00327 /* Printing protocol */
00328 void Stream::print(Object *object)
00329 {
00330     if (object == nil) {
00331         nextPutAll("<nil>");
00332         return;
00333     }
00334     object->printOn(this);
00335 }
00336 
00337 void Stream::print(long number)
00338 {
00339     nextPutAll(String::format("%d", number));
00340 }
00341 
00342 void Stream::print(double number)
00343 {
00344     nextPutAll(String::format("%g", number));
00345 }
00346 
00347 /* Status protocol */
00348 void Stream::close(void)
00349 {
00350     /* Does nothing */
00351 }
00352 
00353 void Stream::commit(void)
00354 {
00355     /* Does nothing */
00356 }
00357 
00358 /* Testing protocol */
00359 bool Stream::isExternalStream(void)
00360 {
00361     return false;
00362 }
00363 
00364 /* Private protocol */
00365 SequenceableCollection *Stream::contentSpeciesFor(long items)
00366 {
00367     return new Array(items);
00368 }

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