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