casa
$Rev:20696$
|
00001 //# OrderedMap.h: Templated associatve array (map) classes with ordered keys 00002 //# Copyright (C) 1993,1994,1995,1996,1999,2000,2001 00003 //# Associated Universities, Inc. Washington DC, USA. 00004 //# 00005 //# This library is free software; you can redistribute it and/or modify it 00006 //# under the terms of the GNU Library General Public License as published by 00007 //# the Free Software Foundation; either version 2 of the License, or (at your 00008 //# option) any later version. 00009 //# 00010 //# This library is distributed in the hope that it will be useful, but WITHOUT 00011 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00012 //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 00013 //# License for more details. 00014 //# 00015 //# You should have received a copy of the GNU Library General Public License 00016 //# along with this library; if not, write to the Free Software Foundation, 00017 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. 00018 //# 00019 //# Correspondence concerning AIPS++ should be addressed as follows: 00020 //# Internet email: aips2-request@nrao.edu. 00021 //# Postal address: AIPS++ Project Office 00022 //# National Radio Astronomy Observatory 00023 //# 520 Edgemont Road 00024 //# Charlottesville, VA 22903-2475 USA 00025 //# 00026 //# $Id: OrderedMap.h 20551 2009-03-25 00:11:33Z Malte.Marquarding $ 00027 00028 #ifndef CASA_ORDEREDMAP_H 00029 #define CASA_ORDEREDMAP_H 00030 00031 #include <casa/aips.h> 00032 #include <casa/Exceptions/Error.h> 00033 #include <casa/Containers/Block.h> 00034 #include <casa/BasicSL/String.h> 00035 #include <casa/Containers/Map.h> 00036 #include <casa/Containers/OrderedPair.h> 00037 #include <casa/Utilities/Register.h> 00038 #include <casa/Utilities/Notice.h> 00039 00040 namespace casa { //#Begin casa namespace 00041 00042 template<class t, class v> class OrderedMap; 00043 template<class t, class v> class OrderedMapRep; 00044 template<class t, class v> class OrderedMapIterRep; 00045 00046 // <category lib=aips sect="Notice"> 00047 // <summary>Message used for OrderedMap notification</summary> 00048 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos=""> 00049 // </reviewed> 00050 // 00051 // This is the message that flows between the OrderedMap 00052 // and the OrderedMap iterators. It allows OrderedMap 00053 // iterators to react to changes as they occur to the 00054 // OrderedMap. 00055 // 00056 template<class t,class v> class OrderedMapNotice : public Notice { 00057 friend class OrderedMapRep<t,v>; 00058 friend class OrderedMapIterRep<t,v>; 00059 private: 00060 enum NoticeType {CLEAR,DEFINE,REMOVE,DELETE} changeType; 00061 uInt modPos; 00062 00063 //*display 1 00064 // 00065 // This is used to construct a list notice. The parameters are: 00066 // <list> 00067 // <item> the change modification position 00068 // <item> the change type 00069 // </list> 00070 // 00071 OrderedMapNotice(uInt pos, NoticeType typ) : changeType(typ), modPos(pos) {} 00072 00073 public: 00074 // 00075 // This function returns the "Notice" type, retrieved 00076 // from the "type registry". 00077 // 00078 uInt type() const {return Register(this);} 00079 00080 // 00081 // This operator can be used to compare two 00082 // "OrderedMapNotice"s. 00083 // 00084 int operator==(const Notice &op) const { 00085 if (type() != op.type()) { 00086 return 0; 00087 } else { 00088 const OrderedMapNotice<t,v> &opD = (const OrderedMapNotice<t,v> &) op; 00089 return (modPos == opD.modPos && changeType == opD.changeType); 00090 } 00091 } 00092 }; 00093 00094 // <summary> Representation class for an Ordered Map</summary> 00095 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos=""> 00096 // </reviewed> 00097 00098 template<class key, class value> class OrderedMapRep : public NoticeSource, public MapRep<key,value> { 00099 friend class OrderedMap<key,value>; 00100 public: 00101 // 00102 // Creates a map with the specified default value, "value", and the 00103 // internal block size. 00104 // 00105 OrderedMapRep (const value&, uInt size); 00106 00107 // 00108 // Creates a map with the specified default value, "value". 00109 // 00110 OrderedMapRep (const value&); 00111 00112 // 00113 // These functions check to see if a mapping is defined between 00114 // the specified key and some value. If one is, a pointer to 00115 // the value is returned, otherwise 0 is returned. 00116 // 00117 //+grp 00118 value *isDefined(const key&); 00119 const value *isDefined(const key&) const; 00120 //-grp 00121 00122 // 00123 // Returns the number of user defined mappings 00124 // 00125 uInt ndefined() const; 00126 00127 // 00128 // Defines a mapping (ie. create a key value mapping) 00129 // 00130 value &define (const key&, const value&); 00131 00132 // 00133 // Undefines a mapping (ie. remove a key value mapping). 00134 // 00135 void remove (const key&); 00136 00137 // 00138 // Clear the entire map (ie. remove all mappings). 00139 // 00140 void clear (); 00141 00142 MapIterRep<key,value> *getRep(Map<key,value> *) const; 00143 00144 MapRep<key,value> *Clone() const; 00145 00146 // 00147 // Get the number of mappings. 00148 // 00149 uInt nused() const { return nrused; } 00150 uInt ntot() const { return nrtot; } 00151 00152 // 00153 // Get or set the Block allocation increment. 00154 // 00155 //+grp 00156 uInt incr() const { return nrincr; } 00157 uInt incr(uInt nri) { return (nrincr = nri); } 00158 //-grp 00159 00160 // 00161 // Removes a map. 00162 // 00163 ~OrderedMapRep (); 00164 00165 enum {OrderedMapRepVersion = 1}; 00166 00167 protected: 00168 // The blocks to hold the keys and values 00169 // and the total, used and increment size of these blocks. 00170 PtrBlock<OrderedPair<key,value>*> kvblk; 00171 uInt nrtot; 00172 uInt nrused; 00173 uInt nrincr; 00174 00175 // The index of the last key used. 00176 uInt lastRef; 00177 00178 // Binary search for the key. 00179 Int findKey (const key&, Bool&) const; 00180 }; 00181 00182 // 00183 // <category lib=aips sect="Containers"> 00184 // <summary>Map with keys ordered</summary> 00185 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos=""> 00186 // </reviewed> 00187 // 00188 // OrderedMap<key,value> is a template class derived from Map. 00189 // It is similar to ListMap, but the keys are kept in order and 00190 // they have to be unique. 00191 // 00192 // It uses a Block to store an array of pointers to the keys and 00193 // the associated values. 00194 // The keys and values themselves are stored on the heap. 00195 // The keys are kept in order to allow a binary search through 00196 // the keys for rapid access. 00197 // 00198 // This is one (simple) implementation of an ordered map. 00199 // It is not suitable for large arrays of keys, since the overhead 00200 // of keeping the keys in order would get too big. 00201 // For large arrays a red-black tree implementation would be better. 00202 // 00203 // Exceptions are raised when new[] is failing, when the next() 00204 // getKey() or getValue() function is failing or when a duplicate key 00205 // is defined. 00206 // 00207 // The AipsIO >> and << operators are defined in <aips/OrdMapIO.h>. 00208 // 00209 template<class key, class value> class OrderedMap : public Map<key,value> { 00210 friend class OrderedMapIterRep<key,value>; 00211 protected: 00212 00213 void throwgetKey(uInt) const; 00214 void throwgetValue(uInt) const; 00215 00216 value &getVal(uInt inx) { 00217 if (!this->Rep || inx >= nused()) 00218 throwgetValue(inx); 00219 return (((OrderedMapRep<key,value> *)(this->Rep))->kvblk[inx]->y()); 00220 } 00221 00222 const value &getVal(uInt inx) const { 00223 if (!this->Rep || inx >= nused()) 00224 throwgetValue(inx); 00225 return (((OrderedMapRep<key,value> *)(this->Rep))->kvblk[inx]->y()); 00226 } 00227 00228 key &getKey (uInt inx) { 00229 if (!this->Rep || inx >= nused()) 00230 throwgetKey(inx); 00231 return (((OrderedMapRep<key,value> *)(this->Rep))->kvblk[inx]->x()); 00232 } 00233 00234 const key &getKey (uInt inx) const { 00235 if (!this->Rep || inx >= nused()) 00236 throwgetKey(inx); 00237 return (((OrderedMapRep<key,value> *)(this->Rep))->kvblk[inx]->x()); 00238 } 00239 00240 public: 00241 // 00242 // Creates a map with the specified default value, "value", and the 00243 // internal block size. 00244 // 00245 OrderedMap (const value& dflt, uInt size) : Map<key,value>(new OrderedMapRep<key,value>(dflt,size)) { } 00246 00247 // 00248 // Creates a map with the specified default value, "value". 00249 // 00250 explicit OrderedMap (const value& dflt) : Map<key,value>(new OrderedMapRep<key,value>(dflt)) { } 00251 00252 // 00253 // Creates a map from another one; use copy semantics. 00254 // 00255 OrderedMap (const OrderedMap<key,value>& other) : Map<key,value>(other.Rep->Clone()) { } 00256 00257 // 00258 // Does nothing, the destruction is taken care of in the base class, i.e. the 00259 // letter contains the guts. 00260 // 00261 ~OrderedMap(); 00262 00263 // 00264 // Assigns this OrderedMap to another with copy semantics. 00265 // 00266 OrderedMap<key,value>& operator= (const OrderedMap<key,value>& other) { 00267 this->SetRep(other.Rep->Clone()); 00268 return *this; 00269 } 00270 00271 // 00272 // Get the number of mappings. 00273 // 00274 uInt nused() const { return ((OrderedMapRep<key,value> *)(this->Rep))->nused(); } 00275 uInt ntot() const { return ((OrderedMapRep<key,value> *)(this->Rep))->ntot(); } 00276 00277 // 00278 // Get or set the Block allocation increment. 00279 // 00280 //+grp 00281 uInt incr() const { return ((OrderedMapRep<key,value> *)(this->Rep))->incr(); } 00282 uInt incr(uInt nri) { return ((OrderedMapRep<key,value> *)(this->Rep))->incr(nri);} 00283 //-grp 00284 00285 enum {OrderedMapVersion = 1}; 00286 }; 00287 00288 00289 // 00290 // <category lib=aips sect="Containers"> 00291 // <summary>OrderedMap iterator "letter"</summary> 00292 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos=""> 00293 // </reviewed> 00294 // 00295 // This is the "letter" which when paired (Const)MapIter "envelope" 00296 // allows traversal of "OrderedMap"s. 00297 // 00298 template<class key, class value> class OrderedMapIterRep : virtual public MapIterRep<key,value>, public NoticeTarget { 00299 protected: 00300 00301 //*display 4 00302 // 00303 // Throw exceptions on behalf of inline functions. 00304 // 00305 //+grp 00306 void thrownext() const; 00307 void throwInvalidIter() const; 00308 //-grp 00309 00310 OrderedMap<key,value> *container; 00311 00312 uInt CurIndex; 00313 00314 public: 00315 00316 // 00317 // Checks to see if the iterator is in a valid state. 00318 // 00319 Bool isValid() const; 00320 00321 // 00322 // Checks to see if the iterator is at one of the 00323 // map extremes, "atEnd()" or "atStart()". 00324 // 00325 //+grp 00326 Bool atEnd() const; 00327 Bool atStart() const; 00328 //-grp 00329 00330 // 00331 // Move the iterator to the beginning of the Map. 00332 // 00333 void toStart(); 00334 00335 // 00336 // Advance the iterator to the next key. 00337 // 00338 //+grp 00339 void operator++(); 00340 void operator++(int); 00341 //-grp 00342 00343 // 00344 // Retrieve the key at the current iterator position. 00345 // 00346 //+grp 00347 const key &getKey () const; 00348 const key &getKey (uInt inx) const { 00349 if (!container || !isValid()) 00350 throwInvalidIter(); 00351 return ((*container).getKey(inx)); 00352 } 00353 //-grp 00354 00355 // 00356 // Retrieve the value at the given index in the internal block 00357 // which stores the representation of the OrderedMap. 00358 // 00359 // <note> This should typically not be used.</note> 00360 // 00361 //+grp 00362 value &getVal(uInt inx) { 00363 if (!container || !isValid()) 00364 throwInvalidIter(); 00365 return ((*container).getVal(inx)); 00366 } 00367 //-grp 00368 00369 // 00370 // Retrieve the value at the current iterator position. 00371 // 00372 //+grp 00373 const value &getVal() const; 00374 const value &getVal(uInt inx) const { 00375 if (!container || !isValid()) 00376 throwInvalidIter(); 00377 return ((*container).getVal(inx)); 00378 } 00379 00380 value &getVal() {return getVal(CurIndex);} 00381 //-grp 00382 00383 00384 MapIterRep<key,value> *Clone() { 00385 OrderedMapIterRep<key,value> *ret = new OrderedMapIterRep<key,value>(container); 00386 return ret; 00387 } 00388 00389 //*display 4 00390 // 00391 // This function is the hook through which OrderedMap 00392 // iterators are notified of changes to the OrderedMap 00393 // which they observe, i.e. changes which may cause 00394 // require iterator update. 00395 // 00396 void notify(const Notice &); 00397 00398 // 00399 // These constructors allow a ListMapIter to be constructed from a 00400 // ListMap. 00401 // 00402 //+grp 00403 OrderedMapIterRep(OrderedMap<key,value> *st) 00404 : MapIterRep<key,value>(st), 00405 NoticeTarget((NoticeSource *)((OrderedMapRep<key,value> *) st->Rep)), 00406 container(st), 00407 CurIndex(0) 00408 {} 00409 00410 OrderedMapIterRep(OrderedMap<key,value> &st) 00411 : MapIterRep<key,value>(st), 00412 NoticeTarget((NoticeSource *)((OrderedMapRep<key,value> *) st.Rep)), 00413 container(&st), 00414 CurIndex(0) 00415 {} 00416 //-grp 00417 00418 enum {OrderedMapIterRepVersion = 1}; 00419 00420 }; 00421 00422 } //#End casa namespace 00423 #ifndef CASACORE_NO_AUTO_TEMPLATES 00424 #include <casa/Containers/OrderedMap.tcc> 00425 #endif //# CASACORE_NO_AUTO_TEMPLATES 00426 #endif