casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
OrderedMap.h
Go to the documentation of this file.
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