oct-map.h

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 1994-2012 John W. Eaton
00004 Copyright (C) 2010 VZLU Prague
00005 
00006 This file is part of Octave.
00007 
00008 Octave is free software; you can redistribute it and/or modify it
00009 under the terms of the GNU General Public License as published by the
00010 Free Software Foundation; either version 3 of the License, or (at your
00011 option) any later version.
00012 
00013 Octave is distributed in the hope that it will be useful, but WITHOUT
00014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00015 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00016 for more details.
00017 
00018 You should have received a copy of the GNU General Public License
00019 along with Octave; see the file COPYING.  If not, see
00020 <http://www.gnu.org/licenses/>.
00021 
00022 */
00023 
00024 #if !defined (octave_oct_map_h)
00025 #define octave_oct_map_h 1
00026 
00027 #include <algorithm>
00028 #include <map>
00029 
00030 #include "Cell.h"
00031 #include "oct-obj.h"
00032 
00033 class string_vector;
00034 
00035 // A class holding a map field->index. Supports reference-counting.
00036 class OCTINTERP_API
00037 octave_fields
00038 {
00039   class fields_rep : public std::map<std::string, octave_idx_type>
00040   {
00041   public:
00042     fields_rep (void) : std::map<std::string, octave_idx_type> (), count (1) { }
00043     fields_rep (const fields_rep& other)
00044       : std::map<std::string, octave_idx_type> (other), count (1) { }
00045 
00046     octave_refcount<int> count;
00047 
00048   private:
00049     fields_rep& operator = (const fields_rep&); // no assignment!
00050   };
00051 
00052   fields_rep *rep;
00053 
00054   static fields_rep *nil_rep (void)
00055     {
00056       static fields_rep nr;
00057       return &nr;
00058     }
00059 
00060 public:
00061 
00062   octave_fields (void) : rep (nil_rep ()) { rep->count++; }
00063   octave_fields (const string_vector&);
00064   octave_fields (const char * const *);
00065 
00066   ~octave_fields (void)
00067     {
00068       if (--rep->count == 0)
00069         delete rep;
00070     }
00071 
00072   void make_unique (void)
00073     {
00074       if (rep->count > 1)
00075         {
00076           fields_rep *r = new fields_rep (*rep);
00077 
00078           if (--rep->count == 0)
00079             delete rep;
00080 
00081           rep = r;
00082         }
00083     }
00084 
00085   octave_fields (const octave_fields& o) : rep (o.rep) { rep->count++; }
00086 
00087   octave_fields&
00088   operator = (const octave_fields& o)
00089     {
00090       o.rep->count++;
00091       if (--rep->count == 0)
00092         delete rep;
00093       rep = o.rep;
00094 
00095       return *this;
00096     }
00097 
00098   // constant iteration support. non-const iteration intentionally unsupported.
00099 
00100   typedef std::map<std::string, octave_idx_type>::const_iterator const_iterator;
00101   typedef const_iterator iterator;
00102 
00103   const_iterator begin (void) const { return rep->begin (); }
00104   const_iterator end (void) const { return rep->end (); }
00105 
00106   std::string key (const_iterator p) const { return p->first; }
00107   octave_idx_type index (const_iterator p) const { return p->second; }
00108 
00109   const_iterator seek (const std::string& k) const
00110     { return rep->find (k); }
00111 
00112   // high-level methods.
00113 
00114   // number of fields.
00115   octave_idx_type nfields (void) const { return rep->size (); }
00116 
00117   // check whether a field exists.
00118   bool isfield (const std::string& name) const;
00119 
00120   // get index of field. return -1 if not exist
00121   octave_idx_type getfield (const std::string& name) const;
00122   // get index of field. add if not exist
00123   octave_idx_type getfield (const std::string& name);
00124   // remove field and return the index. -1 if didn't exist.
00125   octave_idx_type rmfield (const std::string& name);
00126 
00127   // order the fields of this map. creates a permutation
00128   // used to order the fields.
00129   void orderfields (Array<octave_idx_type>& perm);
00130 
00131   // compares two instances for equality up to order of fields.
00132   // returns a permutation needed to bring the fields of *other*
00133   // into the order of *this*.
00134   bool equal_up_to_order (const octave_fields& other,
00135                           octave_idx_type* perm) const;
00136 
00137   bool equal_up_to_order (const octave_fields& other,
00138                           Array<octave_idx_type>& perm) const;
00139 
00140   bool is_same (const octave_fields& other) const
00141     { return rep == other.rep; }
00142 
00143   // Returns the fields as a vector of strings.
00144   string_vector fieldnames (void) const;
00145 
00146   void clear (void)
00147     {
00148       *this = octave_fields ();
00149     }
00150 };
00151 
00152 
00153 class OCTINTERP_API
00154 octave_scalar_map
00155 {
00156 public:
00157 
00158   octave_scalar_map (const octave_fields& k)
00159     : xkeys (k), xvals (k.nfields ()) { }
00160 
00161   octave_scalar_map (void) : xkeys (), xvals () { }
00162 
00163   octave_scalar_map (const string_vector& k)
00164     : xkeys (k), xvals (k.length ()) { }
00165 
00166   octave_scalar_map (const octave_scalar_map& m)
00167     : xkeys (m.xkeys), xvals(m.xvals) { }
00168 
00169   octave_scalar_map& operator = (const octave_scalar_map& m)
00170     {
00171       xkeys = m.xkeys;
00172       xvals = m.xvals;
00173 
00174       return *this;
00175     }
00176 
00177   // iteration support. note that both const and non-const iterators are the
00178   // same. The const/non-const distinction is made by the key & contents method.
00179   typedef octave_fields::const_iterator const_iterator;
00180   typedef const_iterator iterator;
00181 
00182   const_iterator begin (void) const { return xkeys.begin (); }
00183   const_iterator end (void) const { return xkeys.end (); }
00184 
00185   const_iterator seek (const std::string& k) const { return xkeys.seek (k); }
00186 
00187   std::string key (const_iterator p) const
00188     { return xkeys.key (p); }
00189   octave_idx_type index (const_iterator p) const
00190     { return xkeys.index (p); }
00191 
00192   const octave_value& contents (const_iterator p) const
00193     { return xvals[xkeys.index (p)]; }
00194 
00195   octave_value& contents (iterator p)
00196     { return xvals[xkeys.index (p)]; }
00197 
00198   const octave_value& contents (octave_idx_type i) const
00199     { return xvals[i]; }
00200 
00201   octave_value& contents (octave_idx_type i)
00202     { return xvals[i]; }
00203 
00204   // number of fields.
00205   octave_idx_type nfields (void) const { return xkeys.nfields (); }
00206 
00207   // check whether a field exists.
00208   bool isfield (const std::string& name) const
00209     { return xkeys.isfield (name); }
00210 
00211   bool contains (const std::string& name) const
00212     { return isfield (name); }
00213 
00214   string_vector fieldnames (void) const
00215     { return xkeys.fieldnames (); }
00216 
00217   string_vector keys (void) const
00218     { return fieldnames (); }
00219 
00220   // get contents of a given field. empty value if not exist.
00221   octave_value getfield (const std::string& key) const;
00222 
00223   // set contents of a given field. add if not exist.
00224   void setfield (const std::string& key, const octave_value& val);
00225   void assign (const std::string& k, const octave_value& val)
00226     { setfield (k, val); }
00227 
00228   // remove a given field. do nothing if not exist.
00229   void rmfield (const std::string& key);
00230   void del (const std::string& k) { rmfield (k); }
00231 
00232   // return a copy with fields ordered, optionally along with permutation.
00233   octave_scalar_map orderfields (void) const;
00234   octave_scalar_map orderfields (Array<octave_idx_type>& perm) const;
00235   octave_scalar_map orderfields (const octave_scalar_map& other,
00236                                  Array<octave_idx_type>& perm) const;
00237 
00238   // aka getfield/setfield, but the latter returns a reference.
00239   octave_value contents (const std::string& k) const;
00240   octave_value& contents (const std::string& k);
00241 
00242   void clear (void)
00243     {
00244       xkeys.clear ();
00245       xvals.clear ();
00246     }
00247 
00248   friend class octave_map;
00249 
00250 private:
00251 
00252   octave_fields xkeys;
00253   std::vector<octave_value> xvals;
00254 
00255 };
00256 
00257 template<>
00258 inline octave_scalar_map octave_value_extract<octave_scalar_map> (const octave_value& v)
00259   { return v.scalar_map_value (); }
00260 
00261 class OCTINTERP_API
00262 octave_map
00263 {
00264 public:
00265 
00266   octave_map (const octave_fields& k)
00267     : xkeys (k), xvals (k.nfields ()), dimensions () { }
00268 
00269   octave_map (const dim_vector& dv, const octave_fields& k)
00270     : xkeys (k), xvals (k.nfields (), Cell (dv)), dimensions (dv) { }
00271 
00272   typedef octave_scalar_map element_type;
00273 
00274   octave_map (void) : xkeys (), xvals (), dimensions () { }
00275 
00276   octave_map (const dim_vector& dv) : xkeys (), xvals (), dimensions (dv) { }
00277 
00278   octave_map (const string_vector& k)
00279     : xkeys (k), xvals (k.length (), Cell (1, 1)), dimensions (1, 1) { }
00280 
00281   octave_map (const dim_vector& dv, const string_vector& k)
00282     : xkeys (k), xvals (k.length (), Cell (dv)), dimensions (dv) { }
00283 
00284   octave_map (const octave_map& m)
00285     : xkeys (m.xkeys), xvals (m.xvals), dimensions (m.dimensions) { }
00286 
00287   octave_map (const octave_scalar_map& m);
00288 
00289   octave_map (const Octave_map& m);
00290 
00291   octave_map& operator = (const octave_map& m)
00292     {
00293       xkeys = m.xkeys;
00294       xvals = m.xvals;
00295       dimensions = m.dimensions;
00296 
00297       return *this;
00298     }
00299 
00300   // iteration support. note that both const and non-const iterators are the
00301   // same. The const/non-const distinction is made by the key & contents method.
00302   typedef octave_fields::const_iterator const_iterator;
00303   typedef const_iterator iterator;
00304 
00305   const_iterator begin (void) const { return xkeys.begin (); }
00306   const_iterator end (void) const { return xkeys.end (); }
00307 
00308   const_iterator seek (const std::string& k) const { return xkeys.seek (k); }
00309 
00310   std::string key (const_iterator p) const
00311     { return xkeys.key (p); }
00312   octave_idx_type index (const_iterator p) const
00313     { return xkeys.index (p); }
00314 
00315   const Cell& contents (const_iterator p) const
00316     { return xvals[xkeys.index (p)]; }
00317 
00318   Cell& contents (iterator p)
00319     { return xvals[xkeys.index (p)]; }
00320 
00321   const Cell& contents (octave_idx_type i) const
00322     { return xvals[i]; }
00323 
00324   Cell& contents (octave_idx_type i)
00325     { return xvals[i]; }
00326 
00327   // number of fields.
00328   octave_idx_type nfields (void) const { return xkeys.nfields (); }
00329 
00330   // check whether a field exists.
00331   bool isfield (const std::string& name) const
00332     { return xkeys.isfield (name); }
00333 
00334   bool contains (const std::string& name) const
00335     { return isfield (name); }
00336 
00337   string_vector fieldnames (void) const
00338     { return xkeys.fieldnames (); }
00339 
00340   string_vector keys (void) const
00341     { return fieldnames (); }
00342 
00343   // get contents of a given field. empty value if not exist.
00344   Cell getfield (const std::string& key) const;
00345 
00346   // set contents of a given field. add if not exist. checks for
00347   // correct dimensions.
00348   void setfield (const std::string& key, const Cell& val);
00349   void assign (const std::string& k, const Cell& val)
00350     { setfield (k, val); }
00351 
00352   // remove a given field. do nothing if not exist.
00353   void rmfield (const std::string& key);
00354   void del (const std::string& k) { rmfield (k); }
00355 
00356   // return a copy with fields ordered, optionally along with permutation.
00357   octave_map orderfields (void) const;
00358   octave_map orderfields (Array<octave_idx_type>& perm) const;
00359   octave_map orderfields (const octave_map& other,
00360                           Array<octave_idx_type>& perm) const;
00361 
00362   // aka getfield/setfield, but the latter returns a reference.
00363   Cell contents (const std::string& k) const;
00364   Cell& contents (const std::string& k);
00365 
00366   void clear (void)
00367     {
00368       xkeys.clear ();
00369       xvals.clear ();
00370     }
00371 
00372   // The Array-like methods.
00373   octave_idx_type numel (void) const { return dimensions.numel (); }
00374   octave_idx_type length (void) const { return numel (); }
00375   bool is_empty (void) const { return dimensions.any_zero (); }
00376 
00377   octave_idx_type rows (void) const { return dimensions(0); }
00378   octave_idx_type cols (void) const { return dimensions(1); }
00379   octave_idx_type columns (void) const { return dimensions(1); }
00380 
00381   // Extract a scalar substructure.
00382   octave_scalar_map checkelem (octave_idx_type n) const;
00383   octave_scalar_map checkelem (octave_idx_type i, octave_idx_type j) const;
00384 
00385   octave_scalar_map
00386   checkelem (const Array<octave_idx_type>& ra_idx) const;
00387 
00388   octave_scalar_map operator () (octave_idx_type n) const
00389     { return checkelem (n); }
00390   octave_scalar_map operator () (octave_idx_type i, octave_idx_type j) const
00391     { return checkelem (i, j); }
00392 
00393   octave_scalar_map
00394   operator () (const Array<octave_idx_type>& ra_idx) const
00395     { return checkelem (ra_idx); }
00396 
00397   octave_map squeeze (void) const;
00398 
00399   octave_map permute (const Array<int>& vec, bool inv = false) const;
00400 
00401   dim_vector dims (void) const { return dimensions; }
00402 
00403   int ndims (void) const { return dimensions.length (); }
00404 
00405   octave_map transpose (void) const;
00406 
00407   octave_map reshape (const dim_vector& dv) const;
00408 
00409   void resize (const dim_vector& dv, bool fill = false);
00410 
00411   static octave_map
00412   cat (int dim, octave_idx_type n, const octave_scalar_map *map_list);
00413 
00414   static octave_map
00415   cat (int dim, octave_idx_type n, const octave_map *map_list);
00416 
00417   octave_map index (const idx_vector& i, bool resize_ok = false) const;
00418 
00419   octave_map index (const idx_vector& i, const idx_vector& j,
00420                     bool resize_ok = false) const;
00421 
00422   octave_map index (const Array<idx_vector>& ia,
00423                     bool resize_ok = false) const;
00424 
00425   octave_map index (const octave_value_list&, bool resize_ok = false) const;
00426 
00427   octave_map column (octave_idx_type k) const;
00428   octave_map page (octave_idx_type k) const;
00429 
00430   void assign (const idx_vector& i, const octave_map& rhs);
00431 
00432   void assign (const idx_vector& i, const idx_vector& j, const octave_map& rhs);
00433 
00434   void assign (const Array<idx_vector>& ia, const octave_map& rhs);
00435 
00436   void assign (const octave_value_list&, const octave_map& rhs);
00437 
00438   void assign (const octave_value_list& idx, const std::string& k,
00439                const Cell& rhs);
00440 
00441   void delete_elements (const idx_vector& i);
00442 
00443   void delete_elements (int dim, const idx_vector& i);
00444 
00445   void delete_elements (const Array<idx_vector>& ia);
00446 
00447   void delete_elements (const octave_value_list&);
00448 
00449   octave_map concat (const octave_map& rb, const Array<octave_idx_type>& ra_idx);
00450 
00451   // like checkelem, but no check.
00452   octave_scalar_map fast_elem_extract (octave_idx_type n) const;
00453 
00454   // element assignment, no bounds check
00455   bool fast_elem_insert (octave_idx_type n, const octave_scalar_map& rhs);
00456 
00457 private:
00458 
00459   octave_fields xkeys;
00460   std::vector<Cell> xvals;
00461   dim_vector dimensions;
00462 
00463   void optimize_dimensions (void);
00464   void extract_scalar (octave_scalar_map& dest,
00465                        octave_idx_type index) const;
00466   static void do_cat (int dim, octave_idx_type n,
00467                       const octave_scalar_map *map_list, octave_map& retval);
00468   static void do_cat (int dim, octave_idx_type n,
00469                       const octave_map *map_list, octave_map& retval);
00470 };
00471 
00472 template<>
00473 inline octave_map octave_value_extract<octave_map> (const octave_value& v)
00474   { return v.map_value (); }
00475 
00476 // The original Octave_map object. Octave_map and octave_map are convertible to
00477 // each other.
00478 
00479 class
00480 OCTINTERP_API
00481 Octave_map
00482 {
00483  public:
00484 
00485   typedef std::map<std::string, Cell>::iterator iterator;
00486   typedef std::map<std::string, Cell>::const_iterator const_iterator;
00487 
00488   typedef std::list<std::string>::iterator key_list_iterator;
00489   typedef std::list<std::string>::const_iterator const_key_list_iterator;
00490 
00491   // Warning!  You should always use at least two dimensions.
00492 
00493   Octave_map (const dim_vector& dv = dim_vector (0, 0),
00494               const Cell& key_vals = Cell ());
00495 
00496   Octave_map (const std::string& k, const octave_value& value)
00497     : map (), key_list (), dimensions (1, 1)
00498   {
00499     map[k] = value;
00500     key_list.push_back (k);
00501   }
00502 
00503   Octave_map (const string_vector& sv,
00504               const dim_vector& dv = dim_vector (0, 0))
00505     : map (), key_list (), dimensions (dv)
00506   {
00507     for (octave_idx_type i = 0; i < sv.length (); i++)
00508       {
00509         std::string k = sv[i];
00510         map[k] = Cell (dv);
00511         key_list.push_back (k);
00512       }
00513   }
00514 
00515   Octave_map (const std::string& k, const Cell& vals)
00516     : map (), key_list (), dimensions (vals.dims ())
00517   {
00518     map[k] = vals;
00519     key_list.push_back (k);
00520   }
00521 
00522   Octave_map (const std::string& k, const octave_value_list& val_list)
00523     : map (), key_list (), dimensions (1, val_list.length ())
00524   {
00525     map[k] = val_list;
00526     key_list.push_back (k);
00527   }
00528 
00529   Octave_map (const Octave_map& m)
00530     : map (m.map), key_list (m.key_list), dimensions (m.dimensions) { }
00531 
00532   Octave_map (const octave_map& m);
00533 
00534   Octave_map& operator = (const Octave_map& m)
00535     {
00536       if (this != &m)
00537         {
00538           map = m.map;
00539           key_list = m.key_list;
00540           dimensions = m.dimensions;
00541         }
00542 
00543       return *this;
00544     }
00545 
00546   ~Octave_map (void) { }
00547 
00548   Octave_map squeeze (void) const;
00549 
00550   Octave_map permute (const Array<int>& vec, bool inv = false) const;
00551 
00552   // This is the number of keys.
00553   octave_idx_type nfields (void) const { return map.size (); }
00554 
00555   void del (const std::string& k)
00556     {
00557       iterator p = map.find (k);
00558 
00559       if (p != map.end ())
00560         {
00561           map.erase (p);
00562 
00563           key_list_iterator q
00564             = std::find (key_list.begin (), key_list.end (), k);
00565 
00566           assert (q != key_list.end ());
00567 
00568           key_list.erase (q);
00569         }
00570     }
00571 
00572   iterator begin (void) { return iterator (map.begin ()); }
00573   const_iterator begin (void) const { return const_iterator (map.begin ()); }
00574 
00575   iterator end (void) { return iterator (map.end ()); }
00576   const_iterator end (void) const { return const_iterator (map.end ()); }
00577 
00578   std::string key (const_iterator p) const { return p->first; }
00579 
00580   Cell& contents (const std::string& k);
00581   Cell contents (const std::string& k) const;
00582 
00583   Cell& contents (iterator p)
00584     { return p->second; }
00585 
00586   Cell contents (const_iterator p) const
00587     { return p->second; }
00588 
00589   int intfield (const std::string& k, int def_val = 0) const;
00590 
00591   std::string stringfield (const std::string& k,
00592                            const std::string& def_val = std::string ()) const;
00593 
00594   iterator seek (const std::string& k) { return map.find (k); }
00595   const_iterator seek (const std::string& k) const { return map.find (k); }
00596 
00597   bool contains (const std::string& k) const
00598     { return (seek (k) != map.end ()); }
00599 
00600   void clear (void)
00601     {
00602       map.clear ();
00603       key_list.clear ();
00604     }
00605 
00606   string_vector keys (void) const;
00607 
00608   octave_idx_type rows (void) const { return dimensions(0); }
00609 
00610   octave_idx_type columns (void) const { return dimensions(1); }
00611 
00612   dim_vector dims (void) const { return dimensions; }
00613 
00614   int ndims (void) const { return dimensions.length (); }
00615 
00616   Octave_map transpose (void) const;
00617 
00618   Octave_map reshape (const dim_vector& new_dims) const;
00619 
00620   void resize (const dim_vector& dv, bool fill = false);
00621 
00622   octave_idx_type numel (void) const { return dimensions.numel (); }
00623 
00624   Octave_map concat (const Octave_map& rb, const Array<octave_idx_type>& ra_idx);
00625 
00626   Octave_map& maybe_delete_elements (const octave_value_list& idx);
00627 
00628   Octave_map& assign (const octave_value_list& idx, const Octave_map& rhs);
00629 
00630   Octave_map& assign (const octave_value_list& idx, const std::string& k,
00631                       const Cell& rhs);
00632 
00633   Octave_map& assign (const std::string& k, const octave_value& rhs);
00634 
00635   Octave_map& assign (const std::string& k, const Cell& rhs);
00636 
00637   Octave_map index (const octave_value_list& idx,
00638                     bool resize_ok = false) const;
00639 
00640 private:
00641 
00642   // The map of names to values.
00643   std::map<std::string, Cell> map;
00644 
00645   // An extra list of keys, so we can keep track of the order the keys
00646   // are added for compatibility with you know what.
00647   std::list<std::string> key_list;
00648 
00649   // The current size.
00650   mutable dim_vector dimensions;
00651 
00652   void maybe_add_to_key_list (const std::string& k)
00653     {
00654       if (! contains (k))
00655         key_list.push_back (k);
00656     }
00657 };
00658 
00659 #endif
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines