GNU Octave  4.0.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
ov-class.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2007-2015 John W. Eaton
4 Copyright (C) 2009 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 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27 
28 #include <iostream>
29 
30 #include "Array-util.h"
31 #include "byte-swap.h"
32 #include "oct-locbuf.h"
33 #include "lo-mappers.h"
34 
35 #include "Cell.h"
36 #include "defun.h"
37 #include "error.h"
38 #include "file-ops.h"
39 #include "gripes.h"
40 #include "load-path.h"
41 #include "ls-hdf5.h"
42 #include "ls-oct-ascii.h"
43 #include "ls-oct-binary.h"
44 #include "ls-utils.h"
45 #include "mxarray.h"
46 #include "oct-lvalue.h"
47 #include "oct-hdf5.h"
48 #include "ov-class.h"
49 #ifdef HAVE_JAVA
50 #include "ov-java.h"
51 #endif
52 #include "ov-fcn.h"
53 #include "ov-usr-fcn.h"
54 #include "pager.h"
55 #include "parse.h"
56 #include "pr-output.h"
57 #include "toplev.h"
58 #include "unwind-prot.h"
59 #include "variables.h"
60 
61 
62 int octave_class::t_id (-1);
63 
64 const std::string octave_class::t_name ("class");
65 
66 void
68 {
70  (octave_class::t_name, "<unknown>",
71  octave_value (new octave_class ()));
72 }
73 
74 octave_class::octave_class (const octave_map& m, const std::string& id,
75  const octave_value_list& parents)
76  : octave_base_value (), map (m), c_name (id), obsolete_copies (0)
77 {
78  octave_idx_type n = parents.length ();
79 
80  for (octave_idx_type idx = 0; idx < n; idx++)
81  {
82  octave_value parent = parents(idx);
83 
84  if (! parent.is_object ())
85  error ("parents must be objects");
86  else
87  {
88  std::string pcnm = parent.class_name ();
89 
90  if (find_parent_class (pcnm))
91  error ("duplicate class in parent tree");
92  else
93  {
94  parent_list.push_back (pcnm);
95 
96  octave_idx_type nel = map.numel ();
97  octave_idx_type p_nel = parent.numel ();
98 
99  if (nel == 0)
100  {
101  if (p_nel == 0)
102  {
103  // No elements in MAP or the parent class object,
104  // so just add the field name.
105 
106  map.assign (pcnm, Cell (map.dims ()));
107  }
108  else if (p_nel == 1)
109  {
110  if (map.nfields () == 0)
111  {
112  // No elements or fields in MAP, but the
113  // parent is class object with one element.
114  // Resize to match size of parent class and
115  // make the parent a field in MAP.
116 
117  map.resize (parent.dims ());
118 
119  map.assign (pcnm, parent);
120  }
121  else
122  {
123  // No elements in MAP, but we have at least
124  // one field. So don't resize, just add the
125  // field name.
126 
127  map.assign (pcnm, Cell (map.dims ()));
128  }
129  }
130  else if (map.nfields () == 0)
131  {
132  // No elements or fields in MAP and more than one
133  // element in the parent class object, so we can
134  // resize MAP to match parent dimsenions, then
135  // distribute the elements of the parent object to
136  // the elements of MAP.
137 
138  dim_vector parent_dims = parent.dims ();
139 
140  map.resize (parent_dims);
141 
142  Cell c (parent_dims);
143 
144  octave_map pmap = parent.map_value ();
145 
146  std::list<std::string> plist
147  = parent.parent_class_name_list ();
148 
149  for (octave_idx_type i = 0; i < p_nel; i++)
150  c(i) = octave_value (pmap.index (i), pcnm, plist);
151 
152  map.assign (pcnm, c);
153  }
154  else
155  error ("class: parent class dimension mismatch");
156  }
157  else if (nel == 1 && p_nel == 1)
158  {
159  // Simple assignment.
160 
161  map.assign (pcnm, parent);
162  }
163  else
164  {
165  if (p_nel == 1)
166  {
167  // Broadcast the scalar parent class object to
168  // each element of MAP.
169 
170  Cell pcell (map.dims (), parent);
171 
172  map.assign (pcnm, pcell);
173  }
174 
175  else if (nel == p_nel)
176  {
177  // FIXME: is there a better way to do this?
178 
179  // The parent class object has the same number of
180  // elements as the map we are using to create the
181  // new object, so distribute those elements to
182  // each element of the new object by first
183  // splitting the elements of the parent class
184  // object into a cell array with one element per
185  // cell. Then do the assignment all at once.
186 
187  Cell c (parent.dims ());
188 
189  octave_map pmap = parent.map_value ();
190 
191  std::list<std::string> plist
192  = parent.parent_class_name_list ();
193 
194  for (octave_idx_type i = 0; i < p_nel; i++)
195  c(i) = octave_value (pmap.index (i), pcnm, plist);
196 
197  map.assign (pcnm, c);
198  }
199  else
200  error ("class: parent class dimension mismatch");
201  }
202  }
203  }
204  }
205 
206  if (! error_state)
208 }
209 
212 {
213  if (count == obsolete_copies)
214  {
215  // All remaining copies are obsolete. We don't actually need to clone.
216  count++;
217  return this;
218  }
219  else
220  {
221  // In theory, this shouldn't be happening, but it's here just in case.
222  if (count < obsolete_copies)
223  obsolete_copies = 0;
224 
225  return clone ();
226  }
227 }
228 
229 std::string
231 {
232  std::string retval = class_name ();
233 
234  if (nparents () > 0)
235  {
237 
238  // Here we are just looking to see if FCN is a method or constructor
239  // for any class, not specifically this one.
240  if (fcn && (fcn->is_class_method () || fcn->is_class_constructor ()))
241  retval = fcn->dispatch_class ();
242  }
243 
244  return retval;
245 }
246 
247 static void
249 {
250  error ("invalid index for class");
251 }
252 
253 static void
255 {
256  error ("invalid index for class assignment");
257 }
258 
259 static void
260 gripe_invalid_index_type (const std::string& nm, char t)
261 {
262  error ("%s cannot be indexed with %c", nm.c_str (), t);
263 }
264 
265 static void
267 {
268  error ("assignment to class element failed");
269 }
270 
271 Cell
273 {
274  Cell retval;
275 
276  assert (idx.length () == 1);
277 
278  std::string method_class = get_current_method_class ();
279 
280  // Find the class in which this method resides before attempting to access
281  // the requested field.
282 
283  octave_base_value *obvp = find_parent_class (method_class);
284 
285  if (obvp == 0)
286  {
287  error ("malformed class");
288  return retval;
289  }
290 
291  octave_map my_map = (obvp != this) ? obvp->map_value () : map;
292 
293  std::string nm = idx(0).string_value ();
294 
295  if (! error_state)
296  {
297  octave_map::const_iterator p = my_map.seek (nm);
298 
299  if (p != my_map.end ())
300  retval = my_map.contents (p);
301  else
302  error ("class has no member '%s'", nm.c_str ());
303  }
304  else
306 
307  return retval;
308 }
309 
310 Matrix
312 {
314  return octave_base_value::size ();
315 
316  Matrix retval (1, 2, 1.0);
318 
319  if (meth.is_defined ())
320  {
321  count++;
322  octave_value_list args (1, octave_value (this));
323 
324  octave_value_list lv = feval (meth.function_value (), args, 1);
325  if (lv.length () > 0
326  && lv(0).is_matrix_type () && lv(0).dims ().is_vector ())
327  retval = lv(0).matrix_value ();
328  else
329  error ("@%s/size: invalid return value", class_name ().c_str ());
330  }
331  else
332  {
333  dim_vector dv = dims ();
334 
335  int nd = dv.length ();
336 
337  retval.resize (1, nd);
338 
339  for (int i = 0; i < nd; i++)
340  retval(i) = dv(i);
341  }
342 
343  return retval;
344 }
345 
348 {
350  return octave_base_value::numel (idx);
351 
352  octave_idx_type retval = -1;
353  const std::string cn = class_name ();
354 
355  octave_value meth = symbol_table::find_method ("numel", cn);
356 
357  if (meth.is_defined ())
358  {
359  octave_value_list args (idx.length () + 1, octave_value ());
360 
361  count++;
362  args(0) = octave_value (this);
363 
364  for (octave_idx_type i = 0; i < idx.length (); i++)
365  args(i+1) = idx(i);
366 
367  octave_value_list lv = feval (meth.function_value (), args, 1);
368  if (lv.length () == 1 && lv(0).is_scalar_type ())
369  retval = lv(0).idx_type_value (true);
370  else
371  error ("@%s/numel: invalid return value", cn.c_str ());
372  }
373  else
374  retval = octave_base_value::numel (idx);
375 
376  return retval;
377 }
378 
380 octave_class::subsref (const std::string& type,
381  const std::list<octave_value_list>& idx,
382  int nargout)
383 {
384  octave_value_list retval;
385 
387  {
388  // FIXME: this block of code is the same as the body of
389  // octave_struct::subsref. Maybe it could be shared instead of
390  // duplicated.
391 
392  int skip = 1;
393 
394  switch (type[0])
395  {
396  case '(':
397  {
398  if (type.length () > 1 && type[1] == '.')
399  {
400  std::list<octave_value_list>::const_iterator p = idx.begin ();
401  octave_value_list key_idx = *++p;
402 
403  Cell tmp = dotref (key_idx);
404 
405  if (! error_state)
406  {
407  Cell t = tmp.index (idx.front ());
408 
409  retval(0) = (t.length () == 1) ? t(0)
410  : octave_value (t, true);
411 
412  // We handled two index elements, so tell
413  // next_subsref to skip both of them.
414 
415  skip++;
416  }
417  }
418  else
419  retval(0) = octave_value (map.index (idx.front ()),
421  }
422  break;
423 
424  case '.':
425  {
426  if (map.numel () > 0)
427  {
428  Cell t = dotref (idx.front ());
429 
430  retval(0) = (t.length () == 1) ? t(0) : octave_value (t, true);
431  }
432  }
433  break;
434 
435  case '{':
436  gripe_invalid_index_type (type_name (), type[0]);
437  break;
438 
439  default:
440  panic_impossible ();
441  }
442 
443  // FIXME: perhaps there should be an
444  // octave_value_list::next_subsref member function? See also
445  // octave_user_function::subsref.
446 
447  if (idx.size () > 1)
448  retval = retval(0).next_subsref (nargout, type, idx, skip);
449  }
450  else
451  {
452  octave_value meth = symbol_table::find_method ("subsref", class_name ());
453 
454  if (meth.is_defined ())
455  {
456  octave_value_list args;
457 
458  args(1) = make_idx_args (type, idx, "subsref");
459 
460  if (error_state)
461  return octave_value_list ();
462 
463  count++;
464  args(0) = octave_value (this);
465 
466  // FIXME: for Matlab compatibility, let us attempt to set up a proper
467  // value for nargout at least in the simple case where the
468  // cs-list-type expression - i.e., {} or ().x, is the leading one.
469  // Note that Octave does not actually need this, since it will
470  // be able to properly react to varargout a posteriori.
471  bool maybe_cs_list_query = (type[0] == '.' || type[0] == '{'
472  || (type.length () > 1 && type[0] == '('
473  && type[1] == '.'));
474 
475  int true_nargout = nargout;
476 
477  if (maybe_cs_list_query)
478  {
479  // Set up a proper nargout for the subsref call by calling numel.
480  octave_value_list tmp;
481  if (type[0] != '.') tmp = idx.front ();
482  true_nargout = numel (tmp);
483  }
484 
485  retval = feval (meth.function_value (), args, true_nargout);
486 
487  // Since we're handling subsref, return the list in the first value
488  // if it has more than one element, to be able to pass through
489  // rvalue1 calls.
490  if (retval.length () > 1)
491  retval = octave_value (retval, true);
492  }
493  else
494  {
495  if (type.length () == 1 && type[0] == '(')
496  retval(0) = octave_value (map.index (idx.front ()), c_name,
497  parent_list);
498  else
500  }
501  }
502 
503  return retval;
504 }
505 
507 octave_class::numeric_conv (const Cell& val, const std::string& type)
508 {
509  octave_value retval;
510 
511  if (val.length () == 1)
512  {
513  retval = val(0);
514 
515  if (type.length () > 0 && type[0] == '.' && ! retval.is_map ())
516  retval = octave_map ();
517  }
518  else
520 
521  return retval;
522 }
523 
525 octave_class::subsasgn (const std::string& type,
526  const std::list<octave_value_list>& idx,
527  const octave_value& rhs)
528 {
529  count++;
530  return subsasgn_common (octave_value (this), type, idx, rhs);
531 }
532 
534 octave_class::undef_subsasgn (const std::string& type,
535  const std::list<octave_value_list>& idx,
536  const octave_value& rhs)
537 {
538  // For compatibility with Matlab, pass [] as the first argument to the
539  // the subsasgn function when the LHS of an indexed assignment is
540  // undefined.
541 
542  return subsasgn_common (Matrix (), type, idx, rhs);
543 }
544 
547  const std::string& type,
548  const std::list<octave_value_list>& idx,
549  const octave_value& rhs)
550 {
551  octave_value retval;
552 
553  if (! (in_class_method () || called_from_builtin ()))
554  {
555  octave_value meth = symbol_table::find_method ("subsasgn", class_name ());
556 
557  if (meth.is_defined ())
558  {
559  octave_value_list args;
560 
561  if (rhs.is_cs_list ())
562  {
563  octave_value_list lrhs = rhs.list_value ();
564  args.resize (2 + lrhs.length ());
565  for (octave_idx_type i = 0; i < lrhs.length (); i++)
566  args(2+i) = lrhs(i);
567  }
568  else
569  args(2) = rhs;
570 
571  args(1) = make_idx_args (type, idx, "subsasgn");
572 
573  if (error_state)
574  return octave_value_list ();
575 
576  args(0) = obj;
577 
578  // Now comes the magic. Count copies with me:
579  // 1. myself (obsolete)
580  // 2. the copy inside args (obsolete)
581  // 3. the copy in method's symbol table (working)
582  // ... possibly more (not obsolete).
583  //
584  // So we mark 2 copies as obsolete and hold our fingers crossed.
585  // But prior to doing that, check whether the routine is amenable
586  // to the optimization.
587  // It is essential that the handling function doesn't store extra
588  // copies anywhere. If it does, things will not break but the
589  // optimization won't work.
590 
591  octave_value_list tmp;
592 
593  if (obsolete_copies == 0 && meth.is_user_function ()
595  {
596  unwind_protect frame;
598  obsolete_copies = 2;
599 
600  tmp = feval (meth.function_value (), args);
601  }
602  else
603  tmp = feval (meth.function_value (), args);
604 
605  // FIXME: should the subsasgn method be able to return
606  // more than one value?
607 
608  if (tmp.length () > 1)
609  error ("expecting single return value from @%s/subsasgn",
610  class_name ().c_str ());
611 
612  else
613  retval = tmp(0);
614 
615  return retval;
616  }
617  }
618 
619  // Find the class in which this method resides before
620  // attempting to do the indexed assignment.
621 
622  std::string method_class = get_current_method_class ();
623 
624  octave_base_value *obvp = unique_parent_class (method_class);
625  if (obvp != this)
626  {
627 
628  if (obvp)
629  {
630  obvp->subsasgn (type, idx, rhs);
631  if (! error_state)
632  {
633  count++;
634  retval = octave_value (this);
635  }
636  else
638  }
639  else
640  error ("malformed class");
641 
642  return retval;
643  }
644 
645  // FIXME: this block of code is the same as the body of
646  // octave_struct::subsasgn. Maybe it could be shared instead of
647  // duplicated.
648 
649  int n = type.length ();
650 
651  octave_value t_rhs = rhs;
652 
653  if (n > 1 && ! (type.length () == 2 && type[0] == '(' && type[1] == '.'))
654  {
655  switch (type[0])
656  {
657  case '(':
658  {
659  if (type.length () > 1 && type[1] == '.')
660  {
661  std::list<octave_value_list>::const_iterator p = idx.begin ();
662  octave_value_list t_idx = *p;
663 
664  octave_value_list key_idx = *++p;
665 
666  assert (key_idx.length () == 1);
667 
668  std::string key = key_idx(0).string_value ();
669 
670  if (! error_state)
671  {
672  octave_value u;
673 
674  if (! map.contains (key))
675  u = octave_value::empty_conv (type.substr (2), rhs);
676  else
677  {
678  Cell map_val = map.contents (key);
679 
680  Cell map_elt = map_val.index (idx.front (), true);
681 
682  u = numeric_conv (map_elt, type.substr (2));
683  }
684 
685  if (! error_state)
686  {
687  std::list<octave_value_list> next_idx (idx);
688 
689  // We handled two index elements, so subsasgn to
690  // needs to skip both of them.
691 
692  next_idx.erase (next_idx.begin ());
693  next_idx.erase (next_idx.begin ());
694 
695  u.make_unique ();
696 
697  t_rhs = u.subsasgn (type.substr (2), next_idx, rhs);
698  }
699  }
700  else
702  }
703  else
705  }
706  break;
707 
708  case '.':
709  {
710  octave_value_list key_idx = idx.front ();
711 
712  assert (key_idx.length () == 1);
713 
714  std::string key = key_idx(0).string_value ();
715 
716  std::list<octave_value_list> next_idx (idx);
717 
718  next_idx.erase (next_idx.begin ());
719 
720  std::string next_type = type.substr (1);
721 
722  Cell tmpc (1, 1);
723  octave_map::iterator pkey = map.seek (key);
724  if (pkey != map.end ())
725  {
726  map.contents (pkey).make_unique ();
727  tmpc = map.contents (pkey);
728  }
729 
730  // FIXME: better code reuse?
731  if (! error_state)
732  {
733  if (tmpc.numel () == 1)
734  {
735  octave_value& tmp = tmpc(0);
736 
737  if (! tmp.is_defined () || tmp.is_zero_by_zero ())
738  {
739  tmp = octave_value::empty_conv (next_type, rhs);
740  tmp.make_unique (); // probably a no-op.
741  }
742  else
743  // optimization: ignore copy still stored inside our map.
744  tmp.make_unique (1);
745 
746  if (! error_state)
747  t_rhs = tmp.subsasgn (next_type, next_idx, rhs);
748  }
749  else
751  }
752  }
753  break;
754 
755  case '{':
756  gripe_invalid_index_type (type_name (), type[0]);
757  break;
758 
759  default:
760  panic_impossible ();
761  }
762  }
763 
764  if (! error_state)
765  {
766  switch (type[0])
767  {
768  case '(':
769  {
770  if (n > 1 && type[1] == '.')
771  {
772  std::list<octave_value_list>::const_iterator p = idx.begin ();
773  octave_value_list key_idx = *++p;
774 
775  assert (key_idx.length () == 1);
776 
777  std::string key = key_idx(0).string_value ();
778 
779  if (! error_state)
780  {
781  map.assign (idx.front (), key, t_rhs);
782 
783  if (! error_state)
784  {
785  count++;
786  retval = octave_value (this);
787  }
788  else
790  }
791  else
793  }
794  else
795  {
796  if (t_rhs.is_object () || t_rhs.is_map ())
797  {
798  octave_map rhs_map = t_rhs.map_value ();
799 
800  if (! error_state)
801  {
802  map.assign (idx.front (), rhs_map);
803 
804  if (! error_state)
805  {
806  count++;
807  retval = octave_value (this);
808  }
809  else
811  }
812  else
813  error ("invalid class assignment");
814  }
815  else
816  {
817  if (t_rhs.is_empty ())
818  {
819  map.delete_elements (idx.front ());
820 
821  if (! error_state)
822  {
823  count++;
824  retval = octave_value (this);
825  }
826  else
828  }
829  else
830  error ("invalid class assignment");
831  }
832  }
833  }
834  break;
835 
836  case '.':
837  {
838  octave_value_list key_idx = idx.front ();
839 
840  assert (key_idx.length () == 1);
841 
842  std::string key = key_idx(0).string_value ();
843 
844  if (t_rhs.is_cs_list ())
845  {
846  Cell tmp_cell = Cell (t_rhs.list_value ());
847 
848  // The shape of the RHS is irrelevant, we just want
849  // the number of elements to agree and to preserve the
850  // shape of the left hand side of the assignment.
851 
852  if (numel () == tmp_cell.numel ())
853  tmp_cell = tmp_cell.reshape (dims ());
854 
855  map.setfield (key, tmp_cell);
856  }
857  else
858  {
859  Cell tmp_cell(1, 1);
860  tmp_cell(0) = t_rhs.storable_value ();
861  map.setfield (key, tmp_cell);
862  }
863 
864  if (! error_state)
865  {
866  count++;
867  retval = octave_value (this);
868  }
869  else
871  }
872  break;
873 
874  case '{':
875  gripe_invalid_index_type (type_name (), type[0]);
876  break;
877 
878  default:
879  panic_impossible ();
880  }
881  }
882  else
884 
885  return retval;
886 }
887 
889 octave_class::index_vector (bool require_integers) const
890 {
891  idx_vector retval;
892 
893  octave_value meth = symbol_table::find_method ("subsindex", class_name ());
894 
895  if (meth.is_defined ())
896  {
897  octave_value_list args;
898  args(0) = octave_value (new octave_class (map, c_name, parent_list));
899 
900  octave_value_list tmp = feval (meth.function_value (), args, 1);
901 
902  if (!error_state && tmp.length () >= 1)
903  {
904  if (tmp(0).is_object ())
905  error ("subsindex function must return a valid index vector");
906  else
907  // Index vector returned by subsindex is zero based
908  // (why this inconsistency Mathworks?), and so we must
909  // add one to the value returned as the index_vector method
910  // expects it to be one based.
911  retval = do_binary_op (octave_value::op_add, tmp (0),
912  octave_value (1.0)).index_vector (require_integers);
913  }
914  }
915  else
916  error ("no subsindex method defined for class %s",
917  class_name ().c_str ());
918 
919  return retval;
920 }
921 
922 size_t
924 {
925  // Neglect the size of the fieldnames.
926 
927  size_t retval = 0;
928 
929  for (octave_map::const_iterator p = map.begin (); p != map.end (); p++)
930  {
931  std::string key = map.key (p);
932 
934 
935  retval += val.byte_size ();
936  }
937 
938  return retval;
939 }
940 
943 {
944  string_vector retval;
945  gripe_wrong_type_arg ("octave_class::map_keys()", type_name ());
946  return retval;
947 }
948 
950 octave_class::find_parent_class (const std::string& parent_class_name)
951 {
952  octave_base_value* retval = 0;
953 
954  if (parent_class_name == class_name ())
955  retval = this;
956  else
957  {
958  for (std::list<std::string>::iterator pit = parent_list.begin ();
959  pit != parent_list.end ();
960  pit++)
961  {
962  octave_map::const_iterator smap = map.seek (*pit);
963 
964  const Cell& tmp = map.contents (smap);
965 
966  octave_value vtmp = tmp(0);
967 
968  octave_base_value *obvp = vtmp.internal_rep ();
969 
970  retval = obvp->find_parent_class (parent_class_name);
971 
972  if (retval)
973  break;
974  }
975  }
976 
977  return retval;
978 }
979 
981 octave_class::unique_parent_class (const std::string& parent_class_name)
982 {
983  octave_base_value* retval = 0;
984 
985  if (parent_class_name == class_name ())
986  retval = this;
987  else
988  {
989  for (std::list<std::string>::iterator pit = parent_list.begin ();
990  pit != parent_list.end ();
991  pit++)
992  {
993  octave_map::iterator smap = map.seek (*pit);
994 
995  Cell& tmp = map.contents (smap);
996 
997  octave_value& vtmp = tmp(0);
998 
999  octave_base_value *obvp = vtmp.internal_rep ();
1000 
1001  // Use find_parent_class first to avoid uniquifying if not necessary.
1002  retval = obvp->find_parent_class (parent_class_name);
1003 
1004  if (retval)
1005  {
1006  vtmp.make_unique ();
1007  obvp = vtmp.internal_rep ();
1008  retval = obvp->unique_parent_class (parent_class_name);
1009 
1010  break;
1011  }
1012  }
1013  }
1014 
1015  return retval;
1016 }
1017 
1018 bool
1019 octave_class::is_instance_of (const std::string& cls_name) const
1020 {
1021  bool retval = false;
1022 
1023  if (cls_name == class_name ())
1024  retval = true;
1025  else
1026  {
1027  for (std::list<std::string>::const_iterator pit = parent_list.begin ();
1028  pit != parent_list.end ();
1029  pit++)
1030  {
1031  octave_map::const_iterator smap = map.seek (*pit);
1032 
1033  const Cell& tmp = map.contents (smap);
1034 
1035  const octave_value& vtmp = tmp(0);
1036 
1037  retval = vtmp.is_instance_of (cls_name);
1038 
1039  if (retval)
1040  break;
1041  }
1042  }
1043 
1044  return retval;
1045 }
1046 
1049 {
1050  string_vector retval;
1051 
1053 
1054  if (meth.is_defined ())
1055  {
1056  octave_value_list args;
1057  args(0) = octave_value (new octave_class (map, c_name, parent_list));
1058 
1059  octave_value_list tmp = feval (meth.function_value (), args, 1);
1060 
1061  if (!error_state && tmp.length () >= 1)
1062  {
1063  if (tmp(0).is_string ())
1064  retval = tmp(0).all_strings (pad);
1065  else
1066  error ("cname/char method did not return a string");
1067  }
1068  }
1069  else
1070  error ("no char method defined for class %s", class_name ().c_str ());
1071 
1072  return retval;
1073 }
1074 
1075 
1076 void
1077 octave_class::print (std::ostream& os, bool)
1078 {
1079  print_raw (os);
1080 }
1081 
1082 void
1083 octave_class::print_raw (std::ostream& os, bool) const
1084 {
1085  unwind_protect frame;
1086 
1087  indent (os);
1088  os << " <class " << class_name () << ">";
1089  newline (os);
1090 }
1091 
1092 bool
1093 octave_class::print_name_tag (std::ostream& os, const std::string& name) const
1094 {
1095  bool retval = false;
1096 
1097  indent (os);
1098  os << name << " =";
1099  newline (os);
1100  if (! Vcompact_format)
1101  newline (os);
1102 
1103  return retval;
1104 }
1105 
1106 void
1107 octave_class::print_with_name (std::ostream& os, const std::string& name,
1108  bool)
1109 {
1110  octave_value fcn = symbol_table::find_method ("display", class_name ());
1111 
1112  if (fcn.is_defined ())
1113  {
1114  octave_value_list args;
1115 
1116  count++;
1117  args(0) = octave_value (this);
1118 
1119  string_vector arg_names (1);
1120 
1121  arg_names[0] = name;
1122 
1123  args.stash_name_tags (arg_names);
1124 
1125  feval (fcn.function_value (), args);
1126  }
1127  else
1128  {
1129  indent (os);
1130  os << name << " = <class " << class_name () << ">";
1131  newline (os);
1132  }
1133 }
1134 
1135 // Loading a class properly requires an exemplar map entry for success.
1136 // If we don't have one, we attempt to create one by calling the constructor
1137 // with no arguments.
1138 bool
1140 {
1141  bool retval = false;
1142 
1145 
1146  if (it != octave_class::exemplar_map.end ())
1147  retval = true;
1148  else
1149  {
1151 
1152  bool have_ctor = false;
1153 
1154  if (ctor.is_defined () && ctor.is_function ())
1155  {
1156  octave_function *fcn = ctor.function_value ();
1157 
1158  if (fcn && fcn->is_class_constructor (c_name))
1159  have_ctor = true;
1160 
1161  // Something has gone terribly wrong if
1162  // symbol_table::find_method (c_name, c_name) does not return
1163  // a class constructor for the class c_name...
1164  assert (have_ctor);
1165  }
1166 
1167  if (have_ctor)
1168  {
1169  unwind_protect frame;
1170 
1171  // Simulate try/catch.
1172 
1173  interpreter_try (frame);
1174 
1175  octave_value_list result
1176  = ctor.do_multi_index_op (1, octave_value_list ());
1177 
1178  if (! error_state && result.length () == 1)
1179  retval = true;
1180 
1181  error_state = false;
1182  }
1183  else
1184  warning ("no constructor for class %s", c_name.c_str ());
1185  }
1186 
1187  return retval;
1188 }
1189 
1190 void
1192 {
1193  exemplar_map.clear ();
1194 }
1195 
1196 // Load/save does not provide enough information to reconstruct the
1197 // class inheritance structure. reconstruct_parents () attempts to
1198 // do so. If successful, a "true" value is returned.
1199 //
1200 // Note that we don't check the loaded object structure against the
1201 // class structure here so the user's loadobj method has a chance
1202 // to do its magic.
1203 bool
1205 {
1206  bool retval = true;
1207  bool might_have_inheritance = false;
1208  std::string dbgstr = "dork";
1209 
1210  // First, check to see if there might be an issue with inheritance.
1211  for (octave_map::const_iterator p = map.begin (); p != map.end (); p++)
1212  {
1213  std::string key = map.key (p);
1214  Cell val = map.contents (p);
1215  if (val(0).is_object ())
1216  {
1217  dbgstr = "blork";
1218  if (key == val(0).class_name ())
1219  {
1220  might_have_inheritance = true;
1221  dbgstr = "cork";
1222  break;
1223  }
1224  }
1225  }
1226 
1227  if (might_have_inheritance)
1228  {
1231 
1232  if (it == octave_class::exemplar_map.end ())
1233  retval = false;
1234  else
1235  {
1236  octave_class::exemplar_info exmplr = it->second;
1237  parent_list = exmplr.parents ();
1238  for (std::list<std::string>::iterator pit = parent_list.begin ();
1239  pit != parent_list.end ();
1240  pit++)
1241  {
1242  dbgstr = *pit;
1243  bool dbgbool = map.contains (*pit);
1244  if (!dbgbool)
1245  {
1246  retval = false;
1247  break;
1248  }
1249  }
1250  }
1251  }
1252 
1253  return retval;
1254 }
1255 
1256 bool
1257 octave_class::save_ascii (std::ostream& os)
1258 {
1259  os << "# classname: " << class_name () << "\n";
1260  octave_map m;
1261  if (load_path::find_method (class_name (), "saveobj") != std::string ())
1262  {
1263  octave_value in = new octave_class (*this);
1264  octave_value_list tmp = feval ("saveobj", in, 1);
1265  if (! error_state)
1266  m = tmp(0).map_value ();
1267  else
1268  return false;
1269  }
1270  else
1271  m = map_value ();
1272 
1273  os << "# length: " << m.nfields () << "\n";
1274 
1275  octave_map::iterator i = m.begin ();
1276  while (i != m.end ())
1277  {
1278  octave_value val = map.contents (i);
1279 
1280  bool b = save_ascii_data (os, val, m.key (i), false, 0);
1281 
1282  if (! b)
1283  return ! os.fail ();
1284 
1285  i++;
1286  }
1287 
1288  return true;
1289 }
1290 
1291 bool
1292 octave_class::load_ascii (std::istream& is)
1293 {
1294  octave_idx_type len = 0;
1295  std::string classname;
1296  bool success = true;
1297 
1298  if (extract_keyword (is, "classname", classname) && classname != "")
1299  {
1300  if (extract_keyword (is, "length", len) && len >= 0)
1301  {
1302  if (len > 0)
1303  {
1304  octave_map m (map);
1305 
1306  for (octave_idx_type j = 0; j < len; j++)
1307  {
1308  octave_value t2;
1309  bool dummy;
1310 
1311  // recurse to read cell elements
1312  std::string nm
1313  = read_ascii_data (is, std::string (), dummy, t2, j);
1314 
1315  if (! is)
1316  break;
1317 
1318  Cell tcell = t2.is_cell () ? t2.cell_value () : Cell (t2);
1319 
1320  if (error_state)
1321  {
1322  error ("load: internal error loading class elements");
1323  return false;
1324  }
1325 
1326  m.assign (nm, tcell);
1327  }
1328 
1329  if (is)
1330  {
1331  c_name = classname;
1333 
1334  map = m;
1335 
1336  if (! reconstruct_parents ())
1337  warning ("load: unable to reconstruct object inheritance");
1338 
1339  if (load_path::find_method (classname, "loadobj")
1340  != std::string ())
1341  {
1342  octave_value in = new octave_class (*this);
1343  octave_value_list tmp = feval ("loadobj", in, 1);
1344 
1345  if (! error_state)
1346  map = tmp(0).map_value ();
1347  else
1348  success = false;
1349  }
1350  }
1351  else
1352  {
1353  error ("load: failed to load class");
1354  success = false;
1355  }
1356  }
1357  else if (len == 0)
1358  {
1359  map = octave_map (dim_vector (1, 1));
1360  c_name = classname;
1361  }
1362  else
1363  panic_impossible ();
1364  }
1365  else
1366  {
1367  error ("load: failed to extract number of elements in class");
1368  success = false;
1369  }
1370  }
1371  else
1372  {
1373  error ("load: failed to extract name of class");
1374  success = false;
1375  }
1376 
1377  return success;
1378 }
1379 
1380 bool
1381 octave_class::save_binary (std::ostream& os, bool& save_as_floats)
1382 {
1383  int32_t classname_len = class_name ().length ();
1384 
1385  os.write (reinterpret_cast<char *> (&classname_len), 4);
1386  os << class_name ();
1387 
1388  octave_map m;
1389  if (load_path::find_method (class_name (), "saveobj") != std::string ())
1390  {
1391  octave_value in = new octave_class (*this);
1392  octave_value_list tmp = feval ("saveobj", in, 1);
1393  if (! error_state)
1394  m = tmp(0).map_value ();
1395  else
1396  return false;
1397  }
1398  else
1399  m = map_value ();
1400 
1401  int32_t len = m.nfields ();
1402  os.write (reinterpret_cast<char *> (&len), 4);
1403 
1404  octave_map::iterator i = m.begin ();
1405  while (i != m.end ())
1406  {
1407  octave_value val = map.contents (i);
1408 
1409  bool b = save_binary_data (os, val, m.key (i), "", 0, save_as_floats);
1410 
1411  if (! b)
1412  return ! os.fail ();
1413 
1414  i++;
1415  }
1416 
1417  return true;
1418 }
1419 
1420 bool
1421 octave_class::load_binary (std::istream& is, bool swap,
1423 {
1424  bool success = true;
1425 
1426  int32_t classname_len;
1427 
1428  is.read (reinterpret_cast<char *> (&classname_len), 4);
1429  if (! is)
1430  return false;
1431  else if (swap)
1432  swap_bytes<4> (&classname_len);
1433 
1434  {
1435  OCTAVE_LOCAL_BUFFER (char, classname, classname_len+1);
1436  classname[classname_len] = '\0';
1437  if (! is.read (reinterpret_cast<char *> (classname), classname_len))
1438  return false;
1439  c_name = classname;
1440  }
1442 
1443  int32_t len;
1444  if (! is.read (reinterpret_cast<char *> (&len), 4))
1445  return false;
1446  if (swap)
1447  swap_bytes<4> (&len);
1448 
1449  if (len > 0)
1450  {
1451  octave_map m (map);
1452 
1453  for (octave_idx_type j = 0; j < len; j++)
1454  {
1455  octave_value t2;
1456  bool dummy;
1457  std::string doc;
1458 
1459  // recurse to read cell elements
1460  std::string nm = read_binary_data (is, swap, fmt, std::string (),
1461  dummy, t2, doc);
1462 
1463  if (! is)
1464  break;
1465 
1466  Cell tcell = t2.is_cell () ? t2.cell_value () : Cell (t2);
1467 
1468  if (error_state)
1469  {
1470  error ("load: internal error loading class elements");
1471  return false;
1472  }
1473 
1474  m.assign (nm, tcell);
1475  }
1476 
1477  if (is)
1478  {
1479  map = m;
1480 
1481  if (! reconstruct_parents ())
1482  warning ("load: unable to reconstruct object inheritance");
1483 
1484  if (load_path::find_method (c_name, "loadobj") != std::string ())
1485  {
1486  octave_value in = new octave_class (*this);
1487  octave_value_list tmp = feval ("loadobj", in, 1);
1488 
1489  if (! error_state)
1490  map = tmp(0).map_value ();
1491  else
1492  success = false;
1493  }
1494  }
1495  else
1496  {
1497  warning ("load: failed to load class");
1498  success = false;
1499  }
1500  }
1501  else if (len == 0)
1502  map = octave_map (dim_vector (1, 1));
1503  else
1504  panic_impossible ();
1505 
1506  return success;
1507 }
1508 
1509 bool
1510 octave_class::save_hdf5 (octave_hdf5_id loc_id, const char *name, bool save_as_floats)
1511 {
1512 #if defined (HAVE_HDF5)
1513 
1514  hsize_t hdims[3];
1515  hid_t group_hid = -1;
1516  hid_t type_hid = -1;
1517  hid_t space_hid = -1;
1518  hid_t class_hid = -1;
1519  hid_t data_hid = -1;
1520  octave_map m;
1522 
1523 #if HAVE_HDF5_18
1524  group_hid = H5Gcreate (loc_id, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
1525 #else
1526  group_hid = H5Gcreate (loc_id, name, 0);
1527 #endif
1528  if (group_hid < 0)
1529  goto error_cleanup;
1530 
1531  // Add the class name to the group
1532  type_hid = H5Tcopy (H5T_C_S1); H5Tset_size (type_hid, c_name.length () + 1);
1533  if (type_hid < 0)
1534  goto error_cleanup;
1535 
1536  hdims[0] = 0;
1537  space_hid = H5Screate_simple (0 , hdims, 0);
1538  if (space_hid < 0)
1539  goto error_cleanup;
1540 #if HAVE_HDF5_18
1541  class_hid = H5Dcreate (group_hid, "classname", type_hid, space_hid,
1542  H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
1543 #else
1544  class_hid = H5Dcreate (group_hid, "classname", type_hid, space_hid,
1545  H5P_DEFAULT);
1546 #endif
1547  if (class_hid < 0 || H5Dwrite (class_hid, type_hid, H5S_ALL, H5S_ALL,
1548  H5P_DEFAULT, c_name.c_str ()) < 0)
1549  goto error_cleanup;
1550 
1551 #if HAVE_HDF5_18
1552  data_hid = H5Gcreate (group_hid, "value", H5P_DEFAULT, H5P_DEFAULT,
1553  H5P_DEFAULT);
1554 #else
1555  data_hid = H5Gcreate (group_hid, "value", 0);
1556 #endif
1557  if (data_hid < 0)
1558  goto error_cleanup;
1559 
1560  if (load_path::find_method (class_name (), "saveobj") != std::string ())
1561  {
1562  octave_value in = new octave_class (*this);
1563  octave_value_list tmp = feval ("saveobj", in, 1);
1564  if (! error_state)
1565  m = tmp(0).map_value ();
1566  else
1567  goto error_cleanup;
1568  }
1569  else
1570  m = map_value ();
1571 
1572  // recursively add each element of the class to this group
1573  i = m.begin ();
1574  while (i != m.end ())
1575  {
1576  octave_value val = map.contents (i);
1577 
1578  bool retval2 = add_hdf5_data (data_hid, val, m.key (i), "", false,
1579  save_as_floats);
1580 
1581  if (! retval2)
1582  break;
1583 
1584  i++;
1585  }
1586 
1587 error_cleanup:
1588 
1589  if (data_hid > 0)
1590  H5Gclose (data_hid);
1591 
1592  if (class_hid > 0)
1593  H5Dclose (class_hid);
1594 
1595  if (space_hid > 0)
1596  H5Sclose (space_hid);
1597 
1598  if (type_hid > 0)
1599  H5Tclose (type_hid);
1600 
1601  if (group_hid > 0)
1602  H5Gclose (group_hid);
1603 
1604  return true;
1605 
1606 #else
1607  gripe_save ("hdf5");
1608  return false;
1609 #endif
1610 }
1611 
1612 bool
1613 octave_class::load_hdf5 (octave_hdf5_id loc_id, const char *name)
1614 {
1615  bool retval = false;
1616 
1617 #if defined (HAVE_HDF5)
1618 
1619  hid_t group_hid = -1;
1620  hid_t data_hid = -1;
1621  hid_t type_hid = -1;
1622  hid_t type_class_hid = -1;
1623  hid_t space_hid = -1;
1624  hid_t subgroup_hid = -1;
1625  hid_t st_id = -1;
1626 
1627  hdf5_callback_data dsub;
1628 
1629  herr_t retval2 = 0;
1630  octave_map m (dim_vector (1, 1));
1631  int current_item = 0;
1632  hsize_t num_obj = 0;
1633  int slen = 0;
1634  hsize_t rank = 0;
1635 
1636 #if HAVE_HDF5_18
1637  group_hid = H5Gopen (loc_id, name, H5P_DEFAULT);
1638 #else
1639  group_hid = H5Gopen (loc_id, name);
1640 #endif
1641  if (group_hid < 0)
1642  goto error_cleanup;
1643 
1644 #if HAVE_HDF5_18
1645  data_hid = H5Dopen (group_hid, "classname", H5P_DEFAULT);
1646 #else
1647  data_hid = H5Dopen (group_hid, "classname");
1648 #endif
1649 
1650  if (data_hid < 0)
1651  goto error_cleanup;
1652 
1653  type_hid = H5Dget_type (data_hid);
1654 
1655  type_class_hid = H5Tget_class (type_hid);
1656 
1657  if (type_class_hid != H5T_STRING)
1658  goto error_cleanup;
1659 
1660  space_hid = H5Dget_space (data_hid);
1661  rank = H5Sget_simple_extent_ndims (space_hid);
1662 
1663  if (rank != 0)
1664  goto error_cleanup;
1665 
1666  slen = H5Tget_size (type_hid);
1667  if (slen < 0)
1668  goto error_cleanup;
1669 
1670  // do-while loop here to prevent goto crossing initialization of classname
1671  do
1672  {
1673  OCTAVE_LOCAL_BUFFER (char, classname, slen);
1674 
1675  // create datatype for (null-terminated) string to read into:
1676  st_id = H5Tcopy (H5T_C_S1);
1677  H5Tset_size (st_id, slen);
1678 
1679  if (H5Dread (data_hid, st_id, H5S_ALL, H5S_ALL, H5P_DEFAULT,
1680  classname) < 0)
1681  {
1682  H5Tclose (st_id);
1683  H5Dclose (data_hid);
1684  H5Gclose (group_hid);
1685  return false;
1686  }
1687 
1688  H5Tclose (st_id);
1689  H5Dclose (data_hid);
1690  data_hid = -1;
1691 
1692  c_name = classname;
1693  }
1694  while (0);
1696 
1697 #if HAVE_HDF5_18
1698  subgroup_hid = H5Gopen (group_hid, name, H5P_DEFAULT);
1699 #else
1700  subgroup_hid = H5Gopen (group_hid, name);
1701 #endif
1702  H5Gget_num_objs (subgroup_hid, &num_obj);
1703  H5Gclose (subgroup_hid);
1704 
1705  while (current_item < static_cast<int> (num_obj)
1706  && (retval2 = H5Giterate (group_hid, name, &current_item,
1707  hdf5_read_next_data, &dsub)) > 0)
1708  {
1709  octave_value t2 = dsub.tc;
1710 
1711  Cell tcell = t2.is_cell () ? t2.cell_value () : Cell (t2);
1712 
1713  if (error_state)
1714  {
1715  error ("load: internal error loading class elements");
1716  return false;
1717  }
1718 
1719  m.assign (dsub.name, tcell);
1720 
1721  }
1722 
1723  if (retval2 >= 0)
1724  {
1725  map = m;
1726 
1727  if (!reconstruct_parents ())
1728  warning ("load: unable to reconstruct object inheritance");
1729 
1730  if (load_path::find_method (c_name, "loadobj") != std::string ())
1731  {
1732  octave_value in = new octave_class (*this);
1733  octave_value_list tmp = feval ("loadobj", in, 1);
1734 
1735  if (! error_state)
1736  {
1737  map = tmp(0).map_value ();
1738  retval = true;
1739  }
1740  else
1741  retval = false;
1742  }
1743  }
1744 
1745 error_cleanup:
1746  if (data_hid > 0)
1747  H5Dclose (data_hid);
1748 
1749  if (data_hid > 0)
1750  H5Gclose (group_hid);
1751 
1752 #else
1753  gripe_load ("hdf5");
1754 #endif
1755 
1756  return retval;
1757 }
1758 
1759 mxArray *
1761 {
1762  gripe_wrong_type_arg ("octave_class::as_mxArray ()", type_name ());
1763 
1764  return 0;
1765 }
1766 
1767 bool
1769 {
1771 
1772  return (fcn
1773  && (fcn->is_class_method ()
1774  || fcn->is_class_constructor ()
1777  && find_parent_class (fcn->dispatch_class ()));
1778 }
1779 
1781  : field_names (), parent_class_names ()
1782 {
1783  if (obj.is_object ())
1784  {
1785  octave_map m = obj.map_value ();
1786  field_names = m.keys ();
1787 
1789  }
1790  else
1791  error ("invalid call to exemplar_info constructor");
1792 }
1793 
1794 
1795 // A map from class names to lists of fields.
1796 std::map<std::string, octave_class::exemplar_info> octave_class::exemplar_map;
1797 
1798 bool
1800 {
1801  bool retval = true;
1802 
1803  if (obj.is_object ())
1804  {
1805  if (nfields () == obj.nfields ())
1806  {
1807  octave_map obj_map = obj.map_value ();
1808  string_vector obj_fnames = obj_map.keys ();
1809  string_vector fnames = fields ();
1810 
1811  for (octave_idx_type i = 0; i < nfields (); i++)
1812  {
1813  if (obj_fnames[i] != fnames[i])
1814  {
1815  retval = false;
1816  error ("mismatch in field names");
1817  break;
1818  }
1819  }
1820 
1821  if (nparents () == obj.nparents ())
1822  {
1823  std::list<std::string> obj_parents
1824  = obj.parent_class_name_list ();
1825  std::list<std::string> pnames = parents ();
1826 
1827  std::list<std::string>::const_iterator p = obj_parents.begin ();
1828  std::list<std::string>::const_iterator q = pnames.begin ();
1829 
1830  while (p != obj_parents.end ())
1831  {
1832  if (*p++ != *q++)
1833  {
1834  retval = false;
1835  error ("mismatch in parent classes");
1836  break;
1837  }
1838  }
1839  }
1840  else
1841  {
1842  retval = false;
1843  error ("mismatch in number of parent classes");
1844  }
1845  }
1846  else
1847  {
1848  retval = false;
1849  error ("mismatch in number of fields");
1850  }
1851  }
1852  else
1853  {
1854  retval = false;
1855  error ("invalid comparison of class exemplar to non-class object");
1856  }
1857 
1858  return retval;
1859 }
1860 
1861 DEFUN (class, args, ,
1862  "-*- texinfo -*-\n\
1863 @deftypefn {Function File} {@var{classname} =} class (@var{obj})\n\
1864 @deftypefnx {Function File} {} class (@var{s}, @var{id})\n\
1865 @deftypefnx {Function File} {} class (@var{s}, @var{id}, @var{p}, @dots{})\n\
1866 Return the class of the object @var{obj}, or create a class with\n\
1867 fields from structure @var{s} and name (string) @var{id}.\n\
1868 \n\
1869 Additional arguments name a list of parent classes from which the new class\n\
1870 is derived.\n\
1871 @seealso{typeinfo, isa}\n\
1872 @end deftypefn")
1873 {
1874  octave_value retval;
1875 
1876  int nargin = args.length ();
1877 
1878  if (nargin == 0)
1879  print_usage ();
1880  else if (nargin == 1)
1881  // Called for class of object
1882  retval = args(0).class_name ();
1883  else
1884  {
1885  // Called as class constructor
1887 
1888  if (args(1).is_string ())
1889  {
1890  std::string id = args(1).string_value ();
1891 
1892  if (fcn)
1893  {
1894  if (fcn->is_class_constructor (id) || fcn->is_class_method (id))
1895  {
1896  octave_map m = args(0).map_value ();
1897 
1898  if (! error_state)
1899  {
1900  if (nargin == 2)
1901  retval
1902  = octave_value (new octave_class
1903  (m, id, std::list<std::string> ()));
1904  else
1905  {
1906  octave_value_list parents = args.slice (2, nargin-2);
1907 
1908  retval
1909  = octave_value (new octave_class (m, id, parents));
1910  }
1911 
1912  if (! error_state)
1913  {
1915  = octave_class::exemplar_map.find (id);
1916 
1917  if (it == octave_class::exemplar_map.end ())
1918  octave_class::exemplar_map[id]
1919  = octave_class::exemplar_info (retval);
1920  else if (! it->second.compare (retval))
1921  error ("class: object of class '%s' does not match previously constructed objects",
1922  id.c_str ());
1923  }
1924  }
1925  else
1926  error ("class: expecting structure S as first argument");
1927  }
1928  else
1929  error ("class: '%s' is invalid as a class name in this context",
1930  id.c_str ());
1931  }
1932  else
1933  error ("class: invalid call from outside class constructor or method");
1934  }
1935  else
1936  error ("class: ID (class name) must be a string");
1937  }
1938 
1939  return retval;
1940 }
1941 
1942 /*
1943 %!assert (class (1.1), "double");
1944 %!assert (class (single (1.1)), "single");
1945 %!assert (class (uint8 (1)), "uint8");
1946 %!testif HAVE_JAVA
1947 %! jobj = javaObject ("java.lang.StringBuffer");
1948 %! assert (class (jobj), "java.lang.StringBuffer");
1949 
1950 %% Test Input Validation
1951 %!error class ()
1952 */
1953 
1954 DEFUN (isa, args, ,
1955  "-*- texinfo -*-\n\
1956 @deftypefn {Function File} {} isa (@var{obj}, @var{classname})\n\
1957 Return true if @var{obj} is an object from the class @var{classname}.\n\
1958 \n\
1959 @var{classname} may also be one of the following class categories:\n\
1960 \n\
1961 @table @asis\n\
1962 @item @qcode{\"float\"}\n\
1963 Floating point value comprising classes @qcode{\"double\"} and\n\
1964 @qcode{\"single\"}.\n\
1965 \n\
1966 @item @qcode{\"integer\"}\n\
1967 Integer value comprising classes (u)int8, (u)int16, (u)int32, (u)int64.\n\
1968 \n\
1969 @item @qcode{\"numeric\"}\n\
1970 Numeric value comprising either a floating point or integer value.\n\
1971 @end table\n\
1972 \n\
1973 If @var{classname} is a cell array of string, a logical array of the same\n\
1974 size is returned, containing true for each class to which @var{obj}\n\
1975 belongs to.\n\
1976 \n\
1977 @seealso{class, typeinfo}\n\
1978 @end deftypefn")
1979 {
1980  octave_value retval;
1981 
1982  if (args.length () != 2)
1983  {
1984  print_usage ();
1985  return retval;
1986  }
1987 
1988  octave_value obj = args(0); // not const because of find_parent_class ()
1989  const Array<std::string> cls = args(1).cellstr_value ();
1990  if (error_state)
1991  {
1992  error ("isa: CLASSNAME must be a string or cell array of strings");
1993  return retval;
1994  }
1995 
1996  boolNDArray matches (cls.dims (), false);
1997  const octave_idx_type n = cls.numel ();
1998  for (octave_idx_type idx = 0; idx < n; idx++)
1999  {
2000  const std::string cl = cls(idx);
2001  if ((cl == "float" && obj.is_float_type ())
2002  || (cl == "integer" && obj.is_integer_type ())
2003  || (cl == "numeric" && obj.is_numeric_type ())
2004  || obj.class_name () == cl || obj.is_instance_of (cl))
2005  matches(idx) = true;
2006  }
2007  return octave_value (matches);
2008 }
2009 
2010 /*
2011 %!assert (isa ("char", "float"), false)
2012 %!assert (isa (logical (1), "float"), false)
2013 %!assert (isa (double (13), "float"), true)
2014 %!assert (isa (single (13), "float"), true)
2015 %!assert (isa (int8 (13), "float"), false)
2016 %!assert (isa (int16 (13), "float"), false)
2017 %!assert (isa (int32 (13), "float"), false)
2018 %!assert (isa (int64 (13), "float"), false)
2019 %!assert (isa (uint8 (13), "float"), false)
2020 %!assert (isa (uint16 (13), "float"), false)
2021 %!assert (isa (uint32 (13), "float"), false)
2022 %!assert (isa (uint64 (13), "float"), false)
2023 %!assert (isa ("char", "numeric"), false)
2024 %!assert (isa (logical (1), "numeric"), false)
2025 %!assert (isa (double (13), "numeric"), true)
2026 %!assert (isa (single (13), "numeric"), true)
2027 %!assert (isa (int8 (13), "numeric"), true)
2028 %!assert (isa (int16 (13), "numeric"), true)
2029 %!assert (isa (int32 (13), "numeric"), true)
2030 %!assert (isa (int64 (13), "numeric"), true)
2031 %!assert (isa (uint8 (13), "numeric"), true)
2032 %!assert (isa (uint16 (13), "numeric"), true)
2033 %!assert (isa (uint32 (13), "numeric"), true)
2034 %!assert (isa (uint64 (13), "numeric"), true)
2035 %!assert (isa (uint8 (13), "integer"), true)
2036 %!assert (isa (double (13), "integer"), false)
2037 %!assert (isa (single (13), "integer"), false)
2038 %!assert (isa (single (13), {"integer", "float", "single"}), [false true true])
2039 
2040 %!assert (isa (double (13), "double"))
2041 %!assert (isa (single (13), "single"))
2042 %!assert (isa (int8 (13), "int8"))
2043 %!assert (isa (int16 (13), "int16"))
2044 %!assert (isa (int32 (13), "int32"))
2045 %!assert (isa (int64 (13), "int64"))
2046 %!assert (isa (uint8 (13), "uint8"))
2047 %!assert (isa (uint16 (13), "uint16"))
2048 %!assert (isa (uint32 (13), "uint32"))
2049 %!assert (isa (uint64 (13), "uint64"))
2050 %!assert (isa ("string", "char"))
2051 %!assert (isa (true, "logical"))
2052 %!assert (isa (false, "logical"))
2053 %!assert (isa ({1, 2}, "cell"))
2054 %!assert (isa ({1, 2}, {"numeric", "integer", "cell"}), [false false true])
2055 
2056 %!testif HAVE_JAVA
2057 %! ## The first and last assert() are equal on purpose. The assert() in
2058 %! ## the middle with an invalid class name will cause the java code to
2059 %! ## throw exceptions which we then must clear properly (or all other calls
2060 %! ## will fail). So we test this too.
2061 %! assert (isa (javaObject ("java.lang.Double", 10), "java.lang.Number"))
2062 %! assert (isa (javaObject ("java.lang.Double", 10), "not_a_class"), false)
2063 %! assert (isa (javaObject ("java.lang.Double", 10), "java.lang.Number"))
2064 
2065 %!test
2066 %! a.b = 1;
2067 %! assert (isa (a, "struct"));
2068 */
2069 
2070 DEFUN (__parent_classes__, args, ,
2071  "-*- texinfo -*-\n\
2072 @deftypefn {Built-in Function} {} __parent_classes__ (@var{x})\n\
2073 Undocumented internal function.\n\
2074 @end deftypefn")
2075 {
2076  octave_value retval = Cell ();
2077 
2078  if (args.length () == 1)
2079  {
2080  octave_value arg = args(0);
2081 
2082  if (arg.is_object ())
2083  retval = Cell (arg.parent_class_names ());
2084  }
2085  else
2086  print_usage ();
2087 
2088  return retval;
2089 }
2090 
2091 DEFUN (isobject, args, ,
2092  "-*- texinfo -*-\n\
2093 @deftypefn {Built-in Function} {} isobject (@var{x})\n\
2094 Return true if @var{x} is a class object.\n\
2095 @seealso{class, typeinfo, isa, ismethod, isprop}\n\
2096 @end deftypefn")
2097 {
2098  octave_value retval;
2099 
2100  if (args.length () == 1)
2101  retval = args(0).is_object ();
2102  else
2103  print_usage ();
2104 
2105  return retval;
2106 }
2107 
2108 DEFUN (ismethod, args, ,
2109  "-*- texinfo -*-\n\
2110 @deftypefn {Built-in Function} {} ismethod (@var{obj}, @var{method})\n\
2111 Return true if @var{obj} is a class object and the string @var{method}\n\
2112 is a method of this class.\n\
2113 @seealso{isprop, isobject}\n\
2114 @end deftypefn")
2115 {
2116  octave_value retval;
2117 
2118  if (args.length () == 2)
2119  {
2120  octave_value arg = args(0);
2121 
2122  std::string class_name;
2123 
2124  if (arg.is_object ())
2125  class_name = arg.class_name ();
2126  else if (arg.is_string ())
2127  class_name = arg.string_value ();
2128  else
2129  error ("ismethod: expecting object or class name as first argument");
2130 
2131  if (! error_state)
2132  {
2133  std::string method = args(1).string_value ();
2134 
2135  if (! error_state)
2136  {
2137  if (load_path::find_method (class_name, method) != std::string ())
2138  retval = true;
2139  else
2140  retval = false;
2141  }
2142  }
2143  }
2144  else
2145  print_usage ();
2146 
2147  return retval;
2148 }
2149 
2150 DEFUN (__methods__, args, ,
2151  "-*- texinfo -*-\n\
2152 @deftypefn {Built-in Function} {} __methods__ (@var{x})\n\
2153 @deftypefnx {Built-in Function} {} __methods__ (\"classname\")\n\
2154 Internal function.\n\
2155 \n\
2156 Implements @code{methods} for Octave class objects and classnames.\n\
2157 @seealso{methods}\n\
2158 @end deftypefn")
2159 {
2160  octave_value retval;
2161 
2162  // Input validation has already been done in methods.m.
2163  octave_value arg = args(0);
2164 
2165  std::string class_name;
2166 
2167  if (arg.is_object ())
2168  class_name = arg.class_name ();
2169  else if (arg.is_string ())
2170  class_name = arg.string_value ();
2171 
2172  if (! error_state)
2173  {
2174  string_vector sv = load_path::methods (class_name);
2175  retval = Cell (sv);
2176  }
2177 
2178  return retval;
2179 }
2180 
2181 static bool
2182 is_built_in_class (const std::string& cn)
2183 {
2184  static std::set<std::string> built_in_class_names;
2185 
2186  if (built_in_class_names.empty ())
2187  {
2188  built_in_class_names.insert ("double");
2189  built_in_class_names.insert ("single");
2190  built_in_class_names.insert ("cell");
2191  built_in_class_names.insert ("struct");
2192  built_in_class_names.insert ("logical");
2193  built_in_class_names.insert ("char");
2194  built_in_class_names.insert ("function handle");
2195  built_in_class_names.insert ("int8");
2196  built_in_class_names.insert ("uint8");
2197  built_in_class_names.insert ("int16");
2198  built_in_class_names.insert ("uint16");
2199  built_in_class_names.insert ("int32");
2200  built_in_class_names.insert ("uint32");
2201  built_in_class_names.insert ("int64");
2202  built_in_class_names.insert ("uint64");
2203  }
2204 
2205  return built_in_class_names.find (cn) != built_in_class_names.end ();
2206 }
2207 
2208 DEFUN (superiorto, args, ,
2209  "-*- texinfo -*-\n\
2210 @deftypefn {Built-in Function} {} superiorto (@var{class_name}, @dots{})\n\
2211 When called from a class constructor, mark the object currently\n\
2212 constructed as having a higher precedence than @var{class_name}.\n\
2213 \n\
2214 More that one such class can be specified in a single call.\n\
2215 This function may only be called from a class constructor.\n\
2216 @seealso{inferiorto}\n\
2217 @end deftypefn")
2218 {
2219  octave_value retval;
2220 
2222  if ((! fcn) || (! fcn->is_class_constructor ()))
2223  {
2224  error ("superiorto: invalid call from outside class constructor");
2225  return retval;
2226  }
2227 
2228  for (int i = 0; i < args.length (); i++)
2229  {
2230  std::string inf_class = args(i).string_value ();
2231  if (error_state)
2232  {
2233  error ("superiorto: expecting argument to be class name");
2234  break;
2235  }
2236 
2237  // User defined classes always have higher precedence
2238  // than built-in classes
2239  if (is_built_in_class (inf_class))
2240  break;
2241 
2242  std::string sup_class = fcn->name ();
2243  if (! symbol_table::set_class_relationship (sup_class, inf_class))
2244  {
2245  error ("superiorto: opposite precedence already set for %s and %s",
2246  sup_class.c_str (), inf_class.c_str ());
2247  break;
2248  }
2249  }
2250 
2251  return retval;
2252 }
2253 
2254 DEFUN (inferiorto, args, ,
2255  "-*- texinfo -*-\n\
2256 @deftypefn {Built-in Function} {} inferiorto (@var{class_name}, @dots{})\n\
2257 When called from a class constructor, mark the object currently\n\
2258 constructed as having a lower precedence than @var{class_name}.\n\
2259 \n\
2260 More that one such class can be specified in a single call.\n\
2261 This function may only be called from a class constructor.\n\
2262 @seealso{superiorto}\n\
2263 @end deftypefn")
2264 {
2265  octave_value retval;
2266 
2268  if ((! fcn) || (! fcn->is_class_constructor ()))
2269  {
2270  error ("inferiorto: invalid call from outside class constructor");
2271  return retval;
2272  }
2273 
2274  for (int i = 0; i < args.length (); i++)
2275  {
2276  std::string sup_class = args(i).string_value ();
2277  if (error_state)
2278  {
2279  error ("inferiorto: expecting argument to be class name");
2280  break;
2281  }
2282 
2283  if (is_built_in_class (sup_class))
2284  {
2285  error ("inferiorto: cannot give user-defined class lower "
2286  "precedence than built-in class");
2287  break;
2288  }
2289 
2290  std::string inf_class = fcn->name ();
2291  if (! symbol_table::set_class_relationship (sup_class, inf_class))
2292  {
2293  error ("inferiorto: opposite precedence already set for %s and %s",
2294  inf_class.c_str (), sup_class.c_str ());
2295  break;
2296  }
2297  }
2298 
2299  return retval;
2300 }
static octave_value numeric_conv(const Cell &val, const std::string &type)
Definition: ov-class.cc:507
bool called_from_builtin(void)
Definition: ov-base.cc:1647
virtual octave_base_value * unique_parent_class(const std::string &)
Definition: ov-base.h:585
string_vector keys(void) const
Definition: oct-map.h:339
bool is_object(void) const
Definition: ov.h:577
bool in_class_method(void)
Definition: ov-class.cc:1768
idx_vector index_vector(bool require_integers=false) const
Definition: ov-class.cc:889
const Cell & contents(const_iterator p) const
Definition: oct-map.h:314
Definition: Cell.h:35
size_t nparents(void) const
Definition: ov.h:913
static bool is_built_in_class(const std::string &cn)
Definition: ov-class.cc:2182
octave_refcount< octave_idx_type > count
Definition: ov-base.h:818
void gripe_wrong_type_arg(const char *name, const char *s, bool is_error)
Definition: gripes.cc:135
std::list< std::string > parents(void) const
Definition: ov-class.h:266
void delete_elements(const idx_vector &i)
Definition: oct-map.cc:1179
static int t_id
Definition: ov-class.h:219
octave_value_list slice(octave_idx_type offset, octave_idx_type len, bool tags=false) const
Definition: oct-obj.h:107
void resize(octave_idx_type nr, octave_idx_type nc, double rfv=0)
Definition: dMatrix.h:130
void assign(const std::string &k, const Cell &val)
Definition: oct-map.h:348
octave_base_value * clone(void) const
Definition: ov-class.h:71
Cell reshape(const dim_vector &new_dims) const
Definition: Cell.h:90
virtual octave_map map_value(void) const
Definition: ov-base.cc:934
static octave_value find_method(const std::string &name, const std::string &dispatch_type)
Definition: symtab.h:1501
OCTINTERP_API void print_usage(void)
Definition: defun.cc:51
bool save_binary(std::ostream &os, bool &save_as_floats)
Definition: ov-class.cc:1381
octave_value tc
Definition: ls-hdf5.h:150
bool is_function(void) const
Definition: ov.h:695
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:275
void gripe_load(const char *type) const
Definition: ov-base.cc:1258
bool is_instance_of(const std::string &) const
Definition: ov-class.cc:1019
octave_idx_type length(void) const
Definition: oct-obj.h:89
dim_vector dims(void) const
Definition: ov-class.h:119
octave_idx_type nfields(void) const
Definition: ov.h:496
std::list< std::string > parent_class_name_list(void) const
Definition: ov.h:916
const_iterator iterator
Definition: oct-map.h:302
octave_map map_value(void) const
Definition: ov.cc:1585
std::string type_name(void) const
Definition: ov-class.h:210
bool contains(const std::string &name) const
Definition: oct-map.h:333
bool is_numeric_type(void) const
Definition: ov.h:663
bool is_defined(void) const
Definition: ov.h:520
std::string name
Definition: ls-hdf5.h:144
void protect_var(T &var)
#define DEFUN(name, args_name, nargout_name, doc)
Definition: defun.h:44
static void add_to_parent_map(const std::string &classname, const std::list< std::string > &parent_list)
Definition: symtab.h:2249
void error(const char *fmt,...)
Definition: error.cc:476
std::string name(void) const
Definition: ov-fcn.h:161
void indent(std::ostream &os) const
Definition: ov-base.cc:1481
octave_value subsasgn(const std::string &type, const std::list< octave_value_list > &idx, const octave_value &rhs)
Definition: ov-class.cc:525
octave_value_list feval(const std::string &name, const octave_value_list &args, int nargout)
Definition: oct-parse.cc:8625
static const std::string t_name
Definition: ov-class.h:221
virtual bool is_anonymous_function_of_class(const std::string &=std::string()) const
Definition: ov-fcn.h:120
void make_unique(void)
Definition: ov.h:326
static octave_function * current(void)
Definition: toplev.h:146
void gripe_save(const char *type) const
Definition: ov-base.cc:1267
static void gripe_failed_assignment(void)
Definition: ov-class.cc:266
bool is_cell(void) const
Definition: ov.h:529
void interpreter_try(unwind_protect &frame)
Definition: error.cc:2161
octave_idx_type numel(void) const
Definition: oct-map.h:372
herr_t hdf5_read_next_data(hid_t group_id, const char *name, void *dv)
Definition: ls-hdf5.cc:249
Cell dotref(const octave_value_list &idx)
Definition: ov-class.cc:272
bool load_hdf5(octave_hdf5_id loc_id, const char *name)
Definition: ov-class.cc:1613
void newline(std::ostream &os) const
Definition: ov-base.cc:1500
const_iterator end(void) const
Definition: oct-map.h:305
bool is_private_function_of_class(const std::string &nm) const
Definition: ov-fcn.h:116
virtual octave_value subsasgn(const std::string &type, const std::list< octave_value_list > &idx, const octave_value &rhs)
Definition: ov-base.cc:227
std::string dispatch_class(void) const
Definition: ov-fcn.h:101
void print_with_name(std::ostream &os, const std::string &name, bool print_padding=true)
Definition: ov-class.cc:1107
bool is_instance_of(const std::string &cls_name) const
Definition: ov.h:926
void print_raw(std::ostream &os, bool pr_as_read_syntax=false) const
Definition: ov-class.cc:1083
octave_class(void)
Definition: ov-class.h:51
virtual octave_idx_type numel(void) const
Definition: ov-base.h:311
string_vector field_names
Definition: ov-class.h:272
void gripe_indexed_cs_list(void)
Definition: gripes.cc:223
octave_value subsasgn(const std::string &type, const std::list< octave_value_list > &idx, const octave_value &rhs)
Definition: ov.cc:1414
Cell cell_value(void) const
Definition: ov.cc:1566
virtual bool is_class_method(const std::string &=std::string()) const
Definition: ov-fcn.h:92
idx_vector index_vector(bool require_integers=false) const
Definition: ov.h:463
bool is_float_type(void) const
Definition: ov.h:614
octave_map map_value(void) const
Definition: ov-class.h:155
std::map< std::string, exemplar_info >::const_iterator exemplar_const_iterator
Definition: ov-class.h:282
const dim_vector & dims(void) const
Return a const-reference so that dims ()(i) works efficiently.
Definition: Array.h:337
octave_value_list do_multi_index_op(int nargout, const octave_value_list &idx)
Definition: ov.cc:1382
bool load_binary(std::istream &is, bool swap, oct_mach_info::float_format fmt)
Definition: ov-class.cc:1421
octave_value subsasgn_common(const octave_value &obj, const std::string &type, const std::list< octave_value_list > &idx, const octave_value &rhs)
Definition: ov-class.cc:546
bool Vcompact_format
Definition: pr-output.cc:106
std::string extract_keyword(std::istream &is, const char *keyword, const bool next_only)
Definition: ls-oct-ascii.cc:80
static std::map< std::string, exemplar_info > exemplar_map
Definition: ov-class.h:277
virtual octave_base_value * find_parent_class(const std::string &)
Definition: ov-base.h:582
void swap_bytes< 4 >(void *ptr)
Definition: byte-swap.h:59
static octave_function * caller(void)
Definition: toplev.h:176
bool reconstruct_parents(void)
Definition: ov-class.cc:1204
octave_idx_type nfields(void) const
Definition: oct-map.h:327
octave_idx_type numel(const octave_value_list &idx)
Definition: ov.h:395
void make_unique(void)
Definition: Array.h:104
void print(std::ostream &os, bool pr_as_read_syntax=false)
Definition: ov-class.cc:1077
std::string string_value(bool force=false) const
Definition: ov.h:897
static void register_type(void)
Definition: ov-class.cc:67
int obsolete_copies
Definition: ov-class.h:233
bool is_string(void) const
Definition: ov.h:562
bool add_hdf5_data(hid_t loc_id, const octave_value &tc, const std::string &name, const std::string &doc, bool mark_as_global, bool save_as_floats)
Definition: ls-hdf5.cc:868
bool save_ascii_data(std::ostream &os, const octave_value &val_arg, const std::string &name, bool mark_as_global, int precision)
octave_user_function * user_function_value(bool silent=false) const
Definition: ov.cc:1603
int error_state
Definition: error.cc:101
mxArray * as_mxArray(void) const
Definition: ov-class.cc:1760
dim_vector dims(void) const
Definition: oct-map.h:400
#define panic_impossible()
Definition: error.h:33
bool compare(const octave_value &obj) const
Definition: ov-class.cc:1799
bool isa(U *value)
Definition: jit-util.h:201
static std::string find_method(const std::string &class_name, const std::string &meth, std::string &dir_name, const std::string &pack_name=std::string())
Definition: load-path.h:96
std::string read_binary_data(std::istream &is, bool swap, oct_mach_info::float_format fmt, const std::string &filename, bool &global, octave_value &tc, std::string &doc)
std::string key(const_iterator p) const
Definition: oct-map.h:309
octave_idx_type length(void) const
Definition: ov.cc:1525
string_vector all_strings(bool pad) const
Definition: ov-class.cc:1048
Definition: dMatrix.h:35
std::list< std::string > parent_class_names
Definition: ov-class.h:273
string_vector parent_class_names(void) const
Definition: ov.h:919
const_iterator begin(void) const
Definition: oct-map.h:304
virtual Matrix size(void)
Definition: ov-base.cc:142
static void gripe_invalid_index_for_assignment(void)
Definition: ov-class.cc:254
dim_vector dims(void) const
Definition: ov.h:470
static void gripe_invalid_index_type(const std::string &nm, char t)
Definition: ov-class.cc:260
string_vector map_keys(void) const
Definition: ov-class.cc:942
bool print_name_tag(std::ostream &os, const std::string &name) const
Definition: ov-class.cc:1093
double arg(double x)
Definition: lo-mappers.h:37
friend class octave_value
Definition: ov-base.h:206
void setfield(const std::string &key, const Cell &val)
Definition: oct-map.cc:265
octave_function * function_value(bool silent=false) const
Definition: ov.cc:1597
static std::list< std::string > methods(const std::string &class_name, const std::string &pack_name=std::string())
Definition: load-path.h:115
static bool set_class_relationship(const std::string &sup_class, const std::string &inf_class)
Definition: symtab.cc:1122
bool is_map(void) const
Definition: ov.h:574
void warning(const char *fmt,...)
Definition: error.cc:681
octave_idx_type length(void) const
Number of elements in the array.
Definition: Array.h:267
octave_base_value * unique_clone(void)
Definition: ov-class.cc:211
bool is_empty(void) const
Definition: ov.h:526
octave_value make_idx_args(const std::string &type, const std::list< octave_value_list > &idx, const std::string &who)
Definition: ov-base.cc:1570
bool subsasgn_optimization_ok(void)
Definition: ov-usr-fcn.cc:687
octave_base_value * find_parent_class(const std::string &)
Definition: ov-class.cc:950
static void clear_exemplar_map(void)
Definition: ov-class.cc:1191
size_t nparents(void) const
Definition: ov-class.h:133
octave_idx_type nfields(void) const
Definition: ov-class.h:131
static void gripe_invalid_index1(void)
Definition: ov-class.cc:248
bool save_binary_data(std::ostream &os, const octave_value &tc, const std::string &name, const std::string &doc, bool mark_as_global, bool save_as_floats)
octave_map map
Definition: ov-class.h:205
virtual bool is_string(void) const
Definition: ov-base.h:359
static int register_type(const std::string &, const std::string &, const octave_value &)
Definition: ov-typeinfo.cc:64
std::list< std::string > parent_list
Definition: ov-class.h:223
bool is_cs_list(void) const
Definition: ov.h:586
octave_idx_type numel(void) const
Definition: ov-class.h:125
std::string class_name(void) const
Definition: ov.h:1049
Cell index(const octave_value_list &idx, bool resize_ok=false) const
Definition: Cell.cc:159
bool is_object(void) const
Definition: ov-class.h:153
size_t byte_size(void) const
Definition: ov-class.cc:923
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
Definition: oct-locbuf.h:197
const_iterator seek(const std::string &k) const
Definition: oct-map.h:307
bool is_user_function(void) const
Definition: ov.h:701
virtual bool is_class_constructor(const std::string &=std::string()) const
Definition: ov-fcn.h:85
void resize(octave_idx_type n, const octave_value &rfv=octave_value())
Definition: oct-obj.h:93
octave_value undef_subsasgn(const std::string &type, const std::list< octave_value_list > &idx, const octave_value &rhs)
Definition: ov-class.cc:534
octave_value subsref(const std::string &type, const std::list< octave_value_list > &idx)
Definition: ov-class.h:86
octave_value_list list_value(void) const
Definition: ov.cc:1633
octave_idx_type index(const_iterator p) const
Definition: oct-map.h:311
void resize(const dim_vector &dv, bool fill=false)
Definition: oct-map.cc:546
octave_base_value * unique_parent_class(const std::string &)
Definition: ov-class.cc:981
bool load_ascii(std::istream &is)
Definition: ov-class.cc:1292
octave_fields::const_iterator const_iterator
Definition: oct-map.h:301
bool reconstruct_exemplar(void)
Definition: ov-class.cc:1139
octave_base_value * internal_rep(void) const
Definition: ov.h:1114
bool save_ascii(std::ostream &os)
Definition: ov-class.cc:1257
std::string c_name
Definition: ov-class.h:222
octave_value storable_value(void) const
Definition: ov.cc:1930
int length(void) const
Definition: dim-vector.h:281
bool is_zero_by_zero(void) const
Definition: ov.h:680
bool save_hdf5(octave_hdf5_id loc_id, const char *name, bool save_as_floats)
Definition: ov-class.cc:1510
std::string get_current_method_class(void)
Definition: ov-class.cc:230
static octave_value empty_conv(const std::string &type, const octave_value &rhs=octave_value())
Definition: ov.cc:2829
octave_value do_binary_op(octave_value::binary_op op, const octave_value &v1, const octave_value &v2)
Definition: ov.cc:1978
std::string read_ascii_data(std::istream &is, const std::string &filename, bool &global, octave_value &tc, octave_idx_type count)
size_t byte_size(void) const
Definition: ov.h:489
Matrix size(void)
Definition: ov-class.cc:311
std::string class_name(void) const
Definition: ov-class.h:211
bool is_integer_type(void) const
Definition: ov.h:648
void stash_name_tags(const string_vector &nm)
Definition: oct-obj.h:137