00001 /* 00002 * Collection.cc 00003 * 00004 * Smalltalk like class library for C++ 00005 * Abstract collection with common functionality. 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/Collection.h> 00025 #include <stlib/CollectionIterator.h> 00026 #include <stlib/Array.h> 00027 #include <stlib/OrderedCollection.h> 00028 #include <stlib/Set.h> 00029 #include <stlib/String.h> 00030 #include <stlib/Stream.h> 00031 #include <stlib/Visitor.h> 00032 #include <stlib/WriteStream.h> 00033 00034 #include <stlib/Error.h> 00035 00036 /* Class-accessing protocol */ 00037 String *Collection::className(void) const 00038 { 00039 return new String("Collection"); 00040 } 00041 00042 /* Accessing protocol */ 00043 long Collection::capacity(void) const 00044 { 00045 return size(); 00046 } 00047 00048 /* Adding protocol */ 00049 void Collection::addAll(Collection *otherColl) 00050 { 00051 Iterator *i; 00052 for (i = otherColl->iterator(); !i->finished(); i->next()) { 00053 add(i->value()); 00054 } 00055 } 00056 00057 /* Converting protocol */ 00058 Array *Collection::asArray(void) 00059 { 00060 Array *array; 00061 Iterator *i; 00062 int idx; 00063 00064 array = new Array(size()); 00065 for (idx = 0, i = iterator(); !i->finished(); i->next(), idx++) { 00066 array->put(idx, i->value()); 00067 } 00068 delete i; 00069 return array; 00070 } 00071 00072 OrderedCollection *Collection::asOrderedCollection(void) 00073 { 00074 OrderedCollection *coll; 00075 00076 coll = new OrderedCollection(size()); 00077 for (Iterator *i = iterator(); !i->finished(); i->next()) { 00078 coll->addLast(i->value()); 00079 } 00080 return coll; 00081 } 00082 00083 Set *Collection::asSet(void) 00084 { 00085 Set *set; 00086 Iterator *i; 00087 00088 set = new Set(size()); 00089 for (i = iterator(); !i->finished(); i->next()) { 00090 set->add(i->value()); 00091 } 00092 delete i; 00093 return set; 00094 } 00095 00096 /* Enumaration protocol */ 00097 Iterator *Collection::iterator(void) const 00098 { 00099 return new CollectionIterator(this); 00100 } 00101 00102 /* Printing protocol */ 00103 void Collection::printOn(Stream *stream) const 00104 { 00105 Iterator *i; 00106 stream->nextPutAll(className()); 00107 stream->nextPutAll(" ("); 00108 i = iterator(); 00109 while (!i->finished()) { 00110 if (i->value() == nil) stream->nextPutAll("nil"); 00111 else i->value()->printOn(stream); 00112 i->next(); 00113 if (!i->finished()) { 00114 stream->space(); 00115 } 00116 } 00117 stream->nextPut(')'); 00118 delete i; 00119 } 00120 00121 String *Collection::printSeparatedBy(String *separator) const 00122 { 00123 Stream *stream = (new String(20))->writeStream(); 00124 printSeparatedOn(stream, separator); 00125 return dynamic_cast<String *>(stream->contents()); 00126 } 00127 00128 String *Collection::printSeparatedBy(const char *separator) const 00129 { 00130 return printSeparatedBy(new String(separator)); 00131 } 00132 00133 void Collection::printSeparatedOn(Stream *stream, String *separator) const 00134 { 00135 bool first = true; 00136 for (Iterator *i = iterator(); !i->finished(); i->next()) { 00137 if (!first) stream->nextPutAll(separator); 00138 i->value()->printOn(stream); 00139 first = false; 00140 } 00141 } 00142 00143 void Collection::printSeparatedOn(Stream *stream, const char *separator) const 00144 { 00145 printSeparatedOn(stream, new String(separator)); 00146 } 00147 00148 /* Removing protocol */ 00149 void Collection::removeAll(Collection *items) 00150 { 00151 for (Iterator *i = items->iterator(); !i->finished(); i->next()) { 00152 remove(i->value()); 00153 } 00154 } 00155 00156 /* Testing protocol */ 00157 bool Collection::includes(Object *obj) 00158 { 00159 Iterator *i; 00160 00161 for (i = iterator(); !i->finished(); i->next()) { 00162 if (i->value()->isEqual(obj)) { 00163 delete i; 00164 return true; 00165 } 00166 } 00167 delete i; 00168 return false; 00169 } 00170 00171 bool Collection::isByteArray(void) 00172 { 00173 return false; 00174 } 00175 00176 bool Collection::isEmpty(void) 00177 { 00178 return size() == 0; 00179 } 00180 00181 bool Collection::isSequenceable(void) const 00182 { 00183 return false; 00184 } 00185 00186 /* Visiting protocol */ 00187 void Collection::visitBy(Visitor *visitor) 00188 { 00189 visitor->visitCollection(this); 00190 } 00191 00192 /* protected methods */ 00193 /* Private protocol */ 00194 void Collection::emptyCheck(void) 00195 { 00196 if (isEmpty()) 00197 error(new String("This collection is empty."), 00198 new String(__PRETTY_FUNCTION__)); 00199 } 00200 00201 long Collection::growSize(void) 00202 { 00203 long cap = capacity(); 00204 return cap > 2 ? cap : 2; 00205 }