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