GNU Octave  3.8.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
oct-map.h
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1994-2013 John W. Eaton
4 Copyright (C) 2010 VZLU Prague
5 
6 This file is part of Octave.
7 
8 Octave is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
12 
13 Octave is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with Octave; see the file COPYING. If not, see
20 <http://www.gnu.org/licenses/>.
21 
22 */
23 
24 #if !defined (octave_oct_map_h)
25 #define octave_oct_map_h 1
26 
27 #include <algorithm>
28 #include <map>
29 
30 #include "Cell.h"
31 #include "oct-obj.h"
32 
33 class string_vector;
34 
35 // A class holding a map field->index. Supports reference-counting.
38 {
39  class fields_rep : public std::map<std::string, octave_idx_type>
40  {
41  public:
42  fields_rep (void) : std::map<std::string, octave_idx_type> (), count (1) { }
43  fields_rep (const fields_rep& other)
44  : std::map<std::string, octave_idx_type> (other), count (1) { }
45 
47 
48  private:
49  fields_rep& operator = (const fields_rep&); // no assignment!
50  };
51 
53 
54  static fields_rep *nil_rep (void)
55  {
56  static fields_rep nr;
57  return &nr;
58  }
59 
60 public:
61 
62  octave_fields (void) : rep (nil_rep ()) { rep->count++; }
64  octave_fields (const char * const *);
65 
66  ~octave_fields (void)
67  {
68  if (--rep->count == 0)
69  delete rep;
70  }
71 
72  void make_unique (void)
73  {
74  if (rep->count > 1)
75  {
76  fields_rep *r = new fields_rep (*rep);
77 
78  if (--rep->count == 0)
79  delete rep;
80 
81  rep = r;
82  }
83  }
84 
85  octave_fields (const octave_fields& o) : rep (o.rep) { rep->count++; }
86 
88  operator = (const octave_fields& o)
89  {
90  o.rep->count++;
91  if (--rep->count == 0)
92  delete rep;
93  rep = o.rep;
94 
95  return *this;
96  }
97 
98  // constant iteration support. non-const iteration intentionally unsupported.
99 
100  typedef std::map<std::string, octave_idx_type>::const_iterator const_iterator;
102 
103  const_iterator begin (void) const { return rep->begin (); }
104  const_iterator end (void) const { return rep->end (); }
105 
106  std::string key (const_iterator p) const { return p->first; }
107  octave_idx_type index (const_iterator p) const { return p->second; }
108 
109  const_iterator seek (const std::string& k) const
110  { return rep->find (k); }
111 
112  // high-level methods.
113 
114  // number of fields.
115  octave_idx_type nfields (void) const { return rep->size (); }
116 
117  // check whether a field exists.
118  bool isfield (const std::string& name) const;
119 
120  // get index of field. return -1 if not exist
121  octave_idx_type getfield (const std::string& name) const;
122  // get index of field. add if not exist
123  octave_idx_type getfield (const std::string& name);
124  // remove field and return the index. -1 if didn't exist.
125  octave_idx_type rmfield (const std::string& name);
126 
127  // order the fields of this map. creates a permutation
128  // used to order the fields.
129  void orderfields (Array<octave_idx_type>& perm);
130 
131  // compares two instances for equality up to order of fields.
132  // returns a permutation needed to bring the fields of *other*
133  // into the order of *this*.
134  bool equal_up_to_order (const octave_fields& other,
135  octave_idx_type* perm) const;
136 
137  bool equal_up_to_order (const octave_fields& other,
138  Array<octave_idx_type>& perm) const;
139 
140  bool is_same (const octave_fields& other) const
141  { return rep == other.rep; }
142 
143  // Returns the fields as a vector of strings.
144  string_vector fieldnames (void) const;
145 
146  void clear (void)
147  {
148  *this = octave_fields ();
149  }
150 };
151 
152 
155 {
156 public:
157 
159  : xkeys (k), xvals (k.nfields ()) { }
160 
161  octave_scalar_map (void) : xkeys (), xvals () { }
162 
164  : xkeys (k), xvals (k.length ()) { }
165 
167  : xkeys (m.xkeys), xvals(m.xvals) { }
168 
169  octave_scalar_map& operator = (const octave_scalar_map& m)
170  {
171  xkeys = m.xkeys;
172  xvals = m.xvals;
173 
174  return *this;
175  }
176 
177  // iteration support. note that both const and non-const iterators are the
178  // same. The const/non-const distinction is made by the key & contents method.
181 
182  const_iterator begin (void) const { return xkeys.begin (); }
183  const_iterator end (void) const { return xkeys.end (); }
184 
185  const_iterator seek (const std::string& k) const { return xkeys.seek (k); }
186 
187  std::string key (const_iterator p) const
188  { return xkeys.key (p); }
190  { return xkeys.index (p); }
191 
192  const octave_value& contents (const_iterator p) const
193  { return xvals[xkeys.index (p)]; }
194 
195  octave_value& contents (iterator p)
196  { return xvals[xkeys.index (p)]; }
197 
198  const octave_value& contents (octave_idx_type i) const
199  { return xvals[i]; }
200 
202  { return xvals[i]; }
203 
204  // number of fields.
205  octave_idx_type nfields (void) const { return xkeys.nfields (); }
206 
207  // check whether a field exists.
208  bool isfield (const std::string& name) const
209  { return xkeys.isfield (name); }
210 
211  bool contains (const std::string& name) const
212  { return isfield (name); }
213 
214  string_vector fieldnames (void) const
215  { return xkeys.fieldnames (); }
216 
217  string_vector keys (void) const
218  { return fieldnames (); }
219 
220  // get contents of a given field. empty value if not exist.
221  octave_value getfield (const std::string& key) const;
222 
223  // set contents of a given field. add if not exist.
224  void setfield (const std::string& key, const octave_value& val);
225  void assign (const std::string& k, const octave_value& val)
226  { setfield (k, val); }
227 
228  // remove a given field. do nothing if not exist.
229  void rmfield (const std::string& key);
230  void del (const std::string& k) { rmfield (k); }
231 
232  // return a copy with fields ordered, optionally along with permutation.
233  octave_scalar_map orderfields (void) const;
234  octave_scalar_map orderfields (Array<octave_idx_type>& perm) const;
235  octave_scalar_map orderfields (const octave_scalar_map& other,
236  Array<octave_idx_type>& perm) const;
237 
238  // aka getfield/setfield, but the latter returns a reference.
239  octave_value contents (const std::string& k) const;
240  octave_value& contents (const std::string& k);
241 
242  void clear (void)
243  {
244  xkeys.clear ();
245  xvals.clear ();
246  }
247 
248  friend class octave_map;
249 
250 private:
251 
253  std::vector<octave_value> xvals;
254 
255 };
256 
257 template<>
258 inline octave_scalar_map
260 { return v.scalar_map_value (); }
261 
264 {
265 public:
266 
268  : xkeys (k), xvals (k.nfields ()), dimensions () { }
269 
270  octave_map (const dim_vector& dv, const octave_fields& k)
271  : xkeys (k), xvals (k.nfields (), Cell (dv)), dimensions (dv) { }
272 
274 
275  octave_map (void) : xkeys (), xvals (), dimensions () { }
276 
277  octave_map (const dim_vector& dv) : xkeys (), xvals (), dimensions (dv) { }
278 
280  : xkeys (k), xvals (k.length (), Cell (1, 1)), dimensions (1, 1) { }
281 
282  octave_map (const dim_vector& dv, const string_vector& k)
283  : xkeys (k), xvals (k.length (), Cell (dv)), dimensions (dv) { }
284 
286  : xkeys (m.xkeys), xvals (m.xvals), dimensions (m.dimensions) { }
287 
288  octave_map (const octave_scalar_map& m);
289 
290  octave_map (const Octave_map& m);
291 
292  octave_map& operator = (const octave_map& m)
293  {
294  xkeys = m.xkeys;
295  xvals = m.xvals;
296  dimensions = m.dimensions;
297 
298  return *this;
299  }
300 
301  // iteration support. note that both const and non-const iterators are the
302  // same. The const/non-const distinction is made by the key & contents method.
305 
306  const_iterator begin (void) const { return xkeys.begin (); }
307  const_iterator end (void) const { return xkeys.end (); }
308 
309  const_iterator seek (const std::string& k) const { return xkeys.seek (k); }
310 
311  std::string key (const_iterator p) const
312  { return xkeys.key (p); }
314  { return xkeys.index (p); }
315 
316  const Cell& contents (const_iterator p) const
317  { return xvals[xkeys.index (p)]; }
318 
319  Cell& contents (iterator p)
320  { return xvals[xkeys.index (p)]; }
321 
322  const Cell& contents (octave_idx_type i) const
323  { return xvals[i]; }
324 
325  Cell& contents (octave_idx_type i)
326  { return xvals[i]; }
327 
328  // number of fields.
329  octave_idx_type nfields (void) const { return xkeys.nfields (); }
330 
331  // check whether a field exists.
332  bool isfield (const std::string& name) const
333  { return xkeys.isfield (name); }
334 
335  bool contains (const std::string& name) const
336  { return isfield (name); }
337 
338  string_vector fieldnames (void) const
339  { return xkeys.fieldnames (); }
340 
341  string_vector keys (void) const
342  { return fieldnames (); }
343 
344  // get contents of a given field. empty value if not exist.
345  Cell getfield (const std::string& key) const;
346 
347  // set contents of a given field. add if not exist. checks for
348  // correct dimensions.
349  void setfield (const std::string& key, const Cell& val);
350  void assign (const std::string& k, const Cell& val)
351  { setfield (k, val); }
352 
353  // remove a given field. do nothing if not exist.
354  void rmfield (const std::string& key);
355  void del (const std::string& k) { rmfield (k); }
356 
357  // return a copy with fields ordered, optionally along with permutation.
358  octave_map orderfields (void) const;
359  octave_map orderfields (Array<octave_idx_type>& perm) const;
360  octave_map orderfields (const octave_map& other,
361  Array<octave_idx_type>& perm) const;
362 
363  // aka getfield/setfield, but the latter returns a reference.
364  Cell contents (const std::string& k) const;
365  Cell& contents (const std::string& k);
366 
367  void clear (void)
368  {
369  xkeys.clear ();
370  xvals.clear ();
371  }
372 
373  // The Array-like methods.
374  octave_idx_type numel (void) const { return dimensions.numel (); }
375  octave_idx_type length (void) const { return numel (); }
376  bool is_empty (void) const { return dimensions.any_zero (); }
377 
378  octave_idx_type rows (void) const { return dimensions(0); }
379  octave_idx_type cols (void) const { return dimensions(1); }
380  octave_idx_type columns (void) const { return dimensions(1); }
381 
382  // Extract a scalar substructure.
383  octave_scalar_map checkelem (octave_idx_type n) const;
384  octave_scalar_map checkelem (octave_idx_type i, octave_idx_type j) const;
385 
387  checkelem (const Array<octave_idx_type>& ra_idx) const;
388 
389  octave_scalar_map operator () (octave_idx_type n) const
390  { return checkelem (n); }
392  { return checkelem (i, j); }
393 
395  operator () (const Array<octave_idx_type>& ra_idx) const
396  { return checkelem (ra_idx); }
397 
398  octave_map squeeze (void) const;
399 
400  octave_map permute (const Array<int>& vec, bool inv = false) const;
401 
402  dim_vector dims (void) const { return dimensions; }
403 
404  int ndims (void) const { return dimensions.length (); }
405 
406  octave_map transpose (void) const;
407 
408  octave_map reshape (const dim_vector& dv) const;
409 
410  void resize (const dim_vector& dv, bool fill = false);
411 
412  static octave_map
413  cat (int dim, octave_idx_type n, const octave_scalar_map *map_list);
414 
415  static octave_map
416  cat (int dim, octave_idx_type n, const octave_map *map_list);
417 
418  octave_map index (const idx_vector& i, bool resize_ok = false) const;
419 
420  octave_map index (const idx_vector& i, const idx_vector& j,
421  bool resize_ok = false) const;
422 
423  octave_map index (const Array<idx_vector>& ia,
424  bool resize_ok = false) const;
425 
426  octave_map index (const octave_value_list&, bool resize_ok = false) const;
427 
428  octave_map column (octave_idx_type k) const;
429  octave_map page (octave_idx_type k) const;
430 
431  void assign (const idx_vector& i, const octave_map& rhs);
432 
433  void assign (const idx_vector& i, const idx_vector& j, const octave_map& rhs);
434 
435  void assign (const Array<idx_vector>& ia, const octave_map& rhs);
436 
437  void assign (const octave_value_list&, const octave_map& rhs);
438 
439  void assign (const octave_value_list& idx, const std::string& k,
440  const Cell& rhs);
441 
442  void delete_elements (const idx_vector& i);
443 
444  void delete_elements (int dim, const idx_vector& i);
445 
446  void delete_elements (const Array<idx_vector>& ia);
447 
448  void delete_elements (const octave_value_list&);
449 
450  octave_map concat (const octave_map& rb,
451  const Array<octave_idx_type>& ra_idx);
452 
453  // like checkelem, but no check.
454  octave_scalar_map fast_elem_extract (octave_idx_type n) const;
455 
456  // element assignment, no bounds check
457  bool fast_elem_insert (octave_idx_type n, const octave_scalar_map& rhs);
458 
459 private:
460 
462  std::vector<Cell> xvals;
464 
465  void optimize_dimensions (void);
466  void extract_scalar (octave_scalar_map& dest,
467  octave_idx_type index) const;
468  static void do_cat (int dim, octave_idx_type n,
469  const octave_scalar_map *map_list, octave_map& retval);
470  static void do_cat (int dim, octave_idx_type n,
471  const octave_map *map_list, octave_map& retval);
472 };
473 
474 template<>
476 { return v.map_value (); }
477 
478 // The original Octave_map object which is now deprecated.
479 // It was fully deprecated in version 3.8 and should be removed in 3.12.
480 // Octave_map and octave_map are convertible to each other.
481 
482 class
485 {
486 public:
487 
488  typedef std::map<std::string, Cell>::iterator iterator;
489  typedef std::map<std::string, Cell>::const_iterator const_iterator;
490 
491  typedef std::list<std::string>::iterator key_list_iterator;
492  typedef std::list<std::string>::const_iterator const_key_list_iterator;
493 
494  // Warning! You should always use at least two dimensions.
495 
496  Octave_map (const dim_vector& dv = dim_vector (0, 0),
497  const Cell& key_vals = Cell ());
498 
499  Octave_map (const std::string& k, const octave_value& value)
500  : map (), key_list (), dimensions (1, 1)
501  {
502  map[k] = value;
503  key_list.push_back (k);
504  }
505 
507  const dim_vector& dv = dim_vector (0, 0))
508  : map (), key_list (), dimensions (dv)
509  {
510  for (octave_idx_type i = 0; i < sv.length (); i++)
511  {
512  std::string k = sv[i];
513  map[k] = Cell (dv);
514  key_list.push_back (k);
515  }
516  }
517 
518  Octave_map (const std::string& k, const Cell& vals)
519  : map (), key_list (), dimensions (vals.dims ())
520  {
521  map[k] = vals;
522  key_list.push_back (k);
523  }
524 
525  Octave_map (const std::string& k, const octave_value_list& val_list)
526  : map (), key_list (), dimensions (1, val_list.length ())
527  {
528  map[k] = val_list;
529  key_list.push_back (k);
530  }
531 
533  : map (m.map), key_list (m.key_list), dimensions (m.dimensions) { }
534 
535  Octave_map (const octave_map& m);
536 
537  Octave_map& operator = (const Octave_map& m)
538  {
539  if (this != &m)
540  {
541  map = m.map;
542  key_list = m.key_list;
543  dimensions = m.dimensions;
544  }
545 
546  return *this;
547  }
548 
549  ~Octave_map (void) { }
550 
551  Octave_map squeeze (void) const;
552 
553  Octave_map permute (const Array<int>& vec, bool inv = false) const;
554 
555  // This is the number of keys.
556  octave_idx_type nfields (void) const { return map.size (); }
557 
558  void del (const std::string& k)
559  {
560  iterator p = map.find (k);
561 
562  if (p != map.end ())
563  {
564  map.erase (p);
565 
566  key_list_iterator q
567  = std::find (key_list.begin (), key_list.end (), k);
568 
569  assert (q != key_list.end ());
570 
571  key_list.erase (q);
572  }
573  }
574 
575  iterator begin (void) { return iterator (map.begin ()); }
576  const_iterator begin (void) const { return const_iterator (map.begin ()); }
577 
578  iterator end (void) { return iterator (map.end ()); }
579  const_iterator end (void) const { return const_iterator (map.end ()); }
580 
581  std::string key (const_iterator p) const { return p->first; }
582 
583  Cell& contents (const std::string& k);
584  Cell contents (const std::string& k) const;
585 
586  Cell& contents (iterator p)
587  { return p->second; }
588 
589  Cell contents (const_iterator p) const
590  { return p->second; }
591 
592  int intfield (const std::string& k, int def_val = 0) const;
593 
594  std::string stringfield (const std::string& k,
595  const std::string& def_val = std::string ()) const;
596 
597  iterator seek (const std::string& k) { return map.find (k); }
598  const_iterator seek (const std::string& k) const { return map.find (k); }
599 
600  bool contains (const std::string& k) const
601  { return (seek (k) != map.end ()); }
602 
603  void clear (void)
604  {
605  map.clear ();
606  key_list.clear ();
607  }
608 
609  string_vector keys (void) const;
610 
611  octave_idx_type rows (void) const { return dimensions(0); }
612 
613  octave_idx_type columns (void) const { return dimensions(1); }
614 
615  dim_vector dims (void) const { return dimensions; }
616 
617  int ndims (void) const { return dimensions.length (); }
618 
619  Octave_map transpose (void) const;
620 
621  Octave_map reshape (const dim_vector& new_dims) const;
622 
623  void resize (const dim_vector& dv, bool fill = false);
624 
625  octave_idx_type numel (void) const { return dimensions.numel (); }
626 
627  Octave_map concat (const Octave_map& rb,
628  const Array<octave_idx_type>& ra_idx);
629 
630  Octave_map& maybe_delete_elements (const octave_value_list& idx);
631 
632  Octave_map& assign (const octave_value_list& idx, const Octave_map& rhs);
633 
634  Octave_map& assign (const octave_value_list& idx, const std::string& k,
635  const Cell& rhs);
636 
637  Octave_map& assign (const std::string& k, const octave_value& rhs);
638 
639  Octave_map& assign (const std::string& k, const Cell& rhs);
640 
641  Octave_map index (const octave_value_list& idx,
642  bool resize_ok = false) const;
643 
644 private:
645 
646  // The map of names to values.
647  std::map<std::string, Cell> map;
648 
649  // An extra list of keys, so we can keep track of the order the keys
650  // are added for compatibility with you know what.
651  std::list<std::string> key_list;
652 
653  // The current size.
655 
656  void maybe_add_to_key_list (const std::string& k)
657  {
658  if (! contains (k))
659  key_list.push_back (k);
660  }
662 
663 #endif