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

SequenceableCollection.cc

Go to the documentation of this file.
00001 /*
00002  * SequenceableCollection.cc
00003  *
00004  * Smalltalk like class library for C++
00005  * Abstract index-accessible collection.
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/SequenceableCollection.h>
00025 
00026 #include <stlib/Array.h>
00027 #include <stlib/ByteArray.h>
00028 #include <stlib/CollectionIterator.h>
00029 #include <stlib/String.h>
00030 #include <stlib/ReadStream.h>
00031 #include <stlib/ReadAppendStream.h>
00032 #include <stlib/WriteStream.h>
00033 
00034 /* Accessing protocol */
00035 Object *SequenceableCollection::any(void)
00036 {
00037     return first();
00038 }
00039 
00040 Object *SequenceableCollection::first(void)
00041 {
00042     emptyCheck();
00043     return at(0);
00044 }
00045 
00046 Object *SequenceableCollection::last(void)
00047 {
00048     emptyCheck();
00049     return at(size()-1);
00050 }
00051 
00052 void SequenceableCollection::replace(long start, long stop,
00053                                      const SequenceableCollection *collection)
00054 {
00055     if (collection->size() != stop - start)
00056         error(new String("Size of replacement doesn\'t match."),
00057               new String(__PRETTY_FUNCTION__));
00058     replace(start, stop, collection, 0);
00059 }
00060 
00061 void SequenceableCollection::replace(long start, long stop,
00062                                      const SequenceableCollection *replacement,
00063                                      long repStart)
00064 {
00065     long repOff = repStart - start;
00066     if (this == replacement && repStart < start) {
00067         /* Replacement would be overwritten, copy in reverse order. */
00068         for (long i = stop - 1; i >= start; i--)
00069             put(i, replacement->at(repOff + i));
00070     } else {
00071         for (long i = start; i < stop; i++)
00072             put(i, replacement->at(repOff + i));
00073     }
00074 }
00075 
00076 void SequenceableCollection::replaceAll(Object *element, Object *replacement)
00077 {
00078     replaceAll(element, replacement, 0, size());
00079 }
00080 
00081 void SequenceableCollection::replaceAll(Object *element, Object *replacement,
00082                                         long startIndex, long stopIndex)
00083 {
00084     long index = startIndex - 1;
00085 
00086     while ((index = nextIndexOf(element, index+1, stopIndex)) < stopIndex) {
00087         put(index, replacement);
00088     }
00089 }
00090 
00091 long SequenceableCollection::indexOf(Object *element) const
00092 {
00093     long index;
00094 
00095     index = nextIndexOf(element, 0, size());
00096     if (index < 0 || index >= size()) index = -1;
00097     return index;
00098 }
00099 
00100 long SequenceableCollection::lastIndexOf(Object *element) const
00101 {
00102     long index;
00103 
00104     index = prevIndexOf(element, size(), 0);
00105     if (index < 0 || index >= size()) index = -1;
00106     return index;
00107 }
00108 
00109 long SequenceableCollection::nextIndexOf(Object *element, long startIndex,
00110                                          long stopIndex) const
00111 {
00112     for (long index = startIndex; index < stopIndex; index++) {
00113         if (at(index)->isEqual(element))
00114             return index;
00115     }
00116     return stopIndex;
00117 }
00118 
00119 long SequenceableCollection::prevIndexOf(Object *element, long startIndex,
00120                                          long stopIndex) const
00121 {
00122     for (long index = startIndex - 1; index >= stopIndex; index--) {
00123         if (at(index)->isEqual(element))
00124             return index;
00125     }
00126     return stopIndex - 1;
00127 }
00128 
00129 long SequenceableCollection::indexOfSubCollection(SequenceableCollection *coll) const
00130 {
00131     return indexOfSubCollection(coll, 0);
00132 }
00133 
00134 long SequenceableCollection::indexOfSubCollection(SequenceableCollection *coll,
00135                                                   long startIndex) const
00136 {
00137     long subSize = coll->size();
00138     Object *firstElement;
00139     long len, matchIndex;
00140 
00141     if (subSize == 0) return -1;
00142     if (subSize + startIndex > size()) return -1;
00143     firstElement = coll->at(0);
00144     len = size() - subSize + 1;
00145     matchIndex = nextIndexOf(firstElement, startIndex, len);
00146     if (subSize == 1)
00147         return (matchIndex >= 0 && matchIndex < len) ? matchIndex : -1;
00148     while (matchIndex < len) {
00149         long index = 1;
00150         while (this->at(matchIndex + index)->isEqual(coll->at(index))) {
00151             index++;
00152             if (index == subSize) return matchIndex;
00153         }
00154         matchIndex = nextIndexOf(firstElement, matchIndex + 1, len);
00155     }
00156     return -1;
00157 }
00158 
00159 /* Adding protocol */
00160 void SequenceableCollection::grow(void)
00161 {
00162     changeSize(size() + growSize());
00163 }
00164 
00165 void SequenceableCollection::growToAtLeast(long items)
00166 {
00167     if (items < size()) return;
00168     changeSize(items + growSize());
00169 }
00170 
00171 /* Converting protocol */
00172 Array *SequenceableCollection::asArray(void)
00173 {
00174     Array *newArray = new Array(size());
00175     for (long i = 0; i < size(); i++) {
00176         newArray->put(i, at(i));
00177     }
00178     return newArray;
00179 }
00180 
00181 ByteArray *SequenceableCollection::asByteArray(void)
00182 {
00183     shouldNotImplement(new String(__PRETTY_FUNCTION__));
00184     return nil;
00185 }
00186 
00187 String *SequenceableCollection::asString(void)
00188 {
00189     shouldNotImplement(new String(__PRETTY_FUNCTION__));
00190     return nil;
00191 }
00192 
00193 ReadStream *SequenceableCollection::readStream(void)
00194 {
00195     return new ReadStream(this);
00196 }
00197 
00198 ReadAppendStream *SequenceableCollection::readAppendStream(void)
00199 {
00200     return new ReadAppendStream(this);
00201 }
00202 
00203 WriteStream *SequenceableCollection::writeStream(void)
00204 {
00205     return new WriteStream(this);
00206 }
00207 
00208 /* Copying protocol */
00213 Object *SequenceableCollection::copy(long from, long to)
00214 {
00215     SequenceableCollection *newColl;
00216     int newSize = to - from;
00217 
00218     newColl = (SequenceableCollection *) copyEmpty(newSize);
00219     newColl->replace(0, newSize, this, from);
00220     return newColl;
00221 }
00222 
00223 SequenceableCollection *SequenceableCollection::copyReplace(long from, long to,
00224                                                             SequenceableCollection *replacement)
00225 {
00226     SequenceableCollection *newCollection;
00227     long newSize;
00228     long endReplacement;
00229 
00230     newSize = size() - (to - from) + replacement->size();
00231     endReplacement = from + replacement->size();
00232     newCollection = (SequenceableCollection *) copyEmpty(newSize);
00233     newCollection->replace(0, from, this, 0);
00234     newCollection->replace(from, endReplacement, replacement, 0);
00235     newCollection->replace(endReplacement, newSize, this, to);
00236     return newCollection;
00237 }
00238 
00239 SequenceableCollection &SequenceableCollection::operator+(SequenceableCollection &collection)
00240 {
00241     return *copyReplace(size(), size(), &collection);
00242 }
00243 
00244 /* Removing protocol */
00245 Object *SequenceableCollection::remove(Object *)
00246 {
00247     shouldNotImplement(new String(__PRETTY_FUNCTION__));
00248     return nil;
00249 }
00250 
00251 /* Testing protocol */
00252 bool SequenceableCollection::includesSubcollection(SequenceableCollection *coll) const
00253 {
00254     return indexOfSubCollection(coll) >= 0 || coll->isEmpty();
00255 }
00256 
00257 bool SequenceableCollection::isSequenceable(void) const
00258 {
00259     return true;
00260 }
00261 
00262 bool SequenceableCollection::startsWith(SequenceableCollection *coll) const
00263 {
00264     return indexOfSubCollection(coll) == 0 || coll->isEmpty();
00265 }
00266 
00267 bool SequenceableCollection::endsWith(SequenceableCollection *coll) const
00268 {
00269     int start = size() - coll->size();
00270     if (start < 0) return false;
00271     return indexOfSubCollection(coll, start) >= 0 || coll->isEmpty();
00272 }
00273 
00274 /* Enumeration protocol */
00275 Object *SequenceableCollection::privNextForIterator(CollectionIterator *iter) const
00276 {
00277     long index = iter->position();
00278     for (; index < size(); index += 1) {
00279         Object *item = at(index);
00280         if (item != nil) {
00281             iter->position(index);
00282             return item;
00283         }
00284     }
00285     iter->position(index);
00286     return nil;
00287 }

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