1 // %NO_EDIT_WARNING% 2 3 //////////////////////////////////////////////////////////////////////// 4 // 5 // Copyright (C) 2001-2021 The Octave Project Developers 6 // 7 // See the file COPYRIGHT.md in the top-level directory of this 8 // distribution or <https://octave.org/copyright/>. 9 // 10 // This file is part of Octave. 11 // 12 // Octave is free software: you can redistribute it and/or modify it 13 // under the terms of the GNU General Public License as published by 14 // the Free Software Foundation, either version 3 of the License, or 15 // (at your option) any later version. 16 // 17 // Octave is distributed in the hope that it will be useful, but 18 // WITHOUT ANY WARRANTY; without even the implied warranty of 19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 // GNU General Public License for more details. 21 // 22 // You should have received a copy of the GNU General Public License 23 // along with Octave; see the file COPYING. If not, see 24 // <https://www.gnu.org/licenses/>. 25 // 26 //////////////////////////////////////////////////////////////////////// 27 28 /* 29 30 Part of this code was originally distributed as part of Octave Forge under 31 the following terms: 32 33 Author: Paul Kienzle 34 I grant this code to the public domain. 35 2001-03-22 36 37 THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 38 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 39 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 40 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 41 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 42 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 43 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 44 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 45 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 46 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 47 SUCH DAMAGE. 48 49 */ 50 51 #if ! defined (octave_mxarray_h) 52 #define octave_mxarray_h 1 53 54 #include "octave-config.h" 55 56 typedef enum 57 { 58 mxUNKNOWN_CLASS = 0, 59 mxCELL_CLASS, 60 mxSTRUCT_CLASS, 61 mxLOGICAL_CLASS, 62 mxCHAR_CLASS, 63 mxVOID_CLASS, 64 mxDOUBLE_CLASS, 65 mxSINGLE_CLASS, 66 mxINT8_CLASS, 67 mxUINT8_CLASS, 68 mxINT16_CLASS, 69 mxUINT16_CLASS, 70 mxINT32_CLASS, 71 mxUINT32_CLASS, 72 mxINT64_CLASS, 73 mxUINT64_CLASS, 74 mxFUNCTION_CLASS 75 } 76 mxClassID; 77 78 typedef enum 79 { 80 mxREAL = 0, 81 mxCOMPLEX = 1 82 } 83 mxComplexity; 84 85 /* Matlab uses a wide char (uint16) internally, but Octave uses plain char. */ 86 /* typedef Uint16 mxChar; */ 87 typedef char mxChar; 88 89 typedef unsigned char mxLogical; 90 91 /* 92 * FIXME: Mathworks says mwSize, mwIndex should be int generally. 93 * But on 64-bit systems, or when mex -largeArrayDims is used, it is size_t. 94 * mwSignedIndex is supposed to be ptrdiff_t. All of this is confusing. 95 * Its better to conform to the same indexing as the rest of Octave. 96 */ 97 typedef %OCTAVE_IDX_TYPE% mwSize; 98 typedef %OCTAVE_IDX_TYPE% mwIndex; 99 typedef %OCTAVE_IDX_TYPE% mwSignedIndex; 100 101 #if ! defined (MXARRAY_TYPEDEFS_ONLY) 102 103 #include <cstring> 104 #include "error.h" 105 106 class octave_value; 107 class dim_vector; 108 109 #define DO_MUTABLE_METHOD(RET_T, METHOD_CALL) \ 110 RET_T retval = rep->METHOD_CALL; \ 111 \ 112 if (rep->mutation_needed ()) \ 113 { \ 114 maybe_mutate (); \ 115 retval = rep->METHOD_CALL; \ 116 } \ 117 \ 118 return retval 119 120 #define DO_VOID_MUTABLE_METHOD(METHOD_CALL) \ 121 rep->METHOD_CALL; \ 122 \ 123 if (rep->mutation_needed ()) \ 124 { \ 125 maybe_mutate (); \ 126 rep->METHOD_CALL; \ 127 } 128 129 class mxArray; 130 131 // A class to provide the default implementation of some of the 132 // virtual functions declared in the mxArray class. 133 134 class mxArray_base 135 { 136 protected: 137 mxArray_base(void)138 mxArray_base (void) { } 139 140 public: 141 142 virtual mxArray_base * dup (void) const = 0; 143 as_mxArray(void)144 virtual mxArray * as_mxArray (void) const { return nullptr; } 145 146 virtual ~mxArray_base (void) = default; 147 is_octave_value(void)148 virtual bool is_octave_value (void) const { return false; } 149 150 virtual int iscell (void) const = 0; 151 152 virtual int is_char (void) const = 0; 153 is_class(const char * name_arg)154 virtual int is_class (const char *name_arg) const 155 { 156 int retval = 0; 157 158 const char *cname = get_class_name (); 159 160 if (cname && name_arg) 161 retval = ! strcmp (cname, name_arg); 162 163 return retval; 164 } 165 166 virtual int is_complex (void) const = 0; 167 168 virtual int is_double (void) const = 0; 169 170 virtual int is_function_handle (void) const = 0; 171 172 virtual int is_int16 (void) const = 0; 173 174 virtual int is_int32 (void) const = 0; 175 176 virtual int is_int64 (void) const = 0; 177 178 virtual int is_int8 (void) const = 0; 179 180 virtual int is_logical (void) const = 0; 181 182 virtual int is_numeric (void) const = 0; 183 184 virtual int is_single (void) const = 0; 185 186 virtual int is_sparse (void) const = 0; 187 188 virtual int is_struct (void) const = 0; 189 190 virtual int is_uint16 (void) const = 0; 191 192 virtual int is_uint32 (void) const = 0; 193 194 virtual int is_uint64 (void) const = 0; 195 196 virtual int is_uint8 (void) const = 0; 197 is_logical_scalar(void)198 virtual int is_logical_scalar (void) const 199 { 200 return is_logical () && get_number_of_elements () == 1; 201 } 202 203 virtual int is_logical_scalar_true (void) const = 0; 204 205 virtual mwSize get_m (void) const = 0; 206 207 virtual mwSize get_n (void) const = 0; 208 209 virtual mwSize * get_dimensions (void) const = 0; 210 211 virtual mwSize get_number_of_dimensions (void) const = 0; 212 213 virtual void set_m (mwSize m) = 0; 214 215 virtual void set_n (mwSize n) = 0; 216 217 virtual int set_dimensions (mwSize *dims_arg, mwSize ndims_arg) = 0; 218 219 virtual mwSize get_number_of_elements (void) const = 0; 220 221 virtual int isempty (void) const = 0; 222 223 virtual bool is_scalar (void) const = 0; 224 225 virtual mxClassID get_class_id (void) const = 0; 226 227 virtual const char * get_class_name (void) const = 0; 228 229 virtual void set_class_name (const char *name_arg) = 0; 230 231 // The following functions aren't pure virtual because they are only 232 // valid for one type. Making them pure virtual would mean that they 233 // have to be implemented for all derived types, and all of those 234 // would need to throw errors instead of just doing it once here. 235 236 virtual mxArray * get_property(mwIndex,const char *)237 get_property (mwIndex /*idx*/, const char * /*pname*/) const 238 { 239 return nullptr; 240 } 241 set_property(mwIndex,const char *,const mxArray *)242 virtual void set_property (mwIndex /*idx*/, const char * /*pname*/, 243 const mxArray * /*pval*/) 244 { 245 err_invalid_type (); 246 } 247 get_cell(mwIndex)248 virtual mxArray * get_cell (mwIndex /*idx*/) const 249 { 250 err_invalid_type (); 251 } 252 253 virtual void set_cell (mwIndex idx, mxArray *val) = 0; 254 255 virtual double get_scalar (void) const = 0; 256 257 virtual void * get_data (void) const = 0; 258 259 virtual void * get_imag_data (void) const = 0; 260 261 virtual void set_data (void *pr) = 0; 262 263 virtual void set_imag_data (void *pi) = 0; 264 265 virtual mwIndex * get_ir (void) const = 0; 266 267 virtual mwIndex * get_jc (void) const = 0; 268 269 virtual mwSize get_nzmax (void) const = 0; 270 271 virtual void set_ir (mwIndex *ir) = 0; 272 273 virtual void set_jc (mwIndex *jc) = 0; 274 275 virtual void set_nzmax (mwSize nzmax) = 0; 276 277 virtual int add_field (const char *key) = 0; 278 279 virtual void remove_field (int key_num) = 0; 280 281 virtual mxArray * get_field_by_number (mwIndex index, int key_num) const = 0; 282 283 virtual void 284 set_field_by_number (mwIndex index, int key_num, mxArray *val) = 0; 285 286 virtual int get_number_of_fields (void) const = 0; 287 288 virtual const char * get_field_name_by_number (int key_num) const = 0; 289 290 virtual int get_field_number (const char *key) const = 0; 291 292 virtual int get_string (char *buf, mwSize buflen) const = 0; 293 294 virtual char * array_to_string (void) const = 0; 295 296 virtual mwIndex calc_single_subscript (mwSize nsubs, mwIndex *subs) const = 0; 297 298 virtual std::size_t get_element_size (void) const = 0; 299 mutation_needed(void)300 virtual bool mutation_needed (void) const { return false; } 301 mutate(void)302 virtual mxArray * mutate (void) const { return nullptr; } 303 304 virtual octave_value as_octave_value (void) const = 0; 305 306 protected: 307 mxArray_base(const mxArray_base &)308 mxArray_base (const mxArray_base&) { } 309 err_invalid_type(void)310 OCTAVE_NORETURN void err_invalid_type (void) const 311 { 312 error ("invalid type for operation"); 313 } 314 }; 315 316 // The main interface class. The representation can be based on an 317 // octave_value object or a separate object that tries to reproduce 318 // the semantics of mxArray objects in Matlab more directly. 319 320 class mxArray 321 { 322 public: 323 324 mxArray (const octave_value& ov); 325 326 mxArray (mxClassID id, mwSize ndims, const mwSize *dims, 327 mxComplexity flag = mxREAL, bool init = true); 328 329 mxArray (mxClassID id, const dim_vector& dv, mxComplexity flag = mxREAL); 330 331 mxArray (mxClassID id, mwSize m, mwSize n, 332 mxComplexity flag = mxREAL, bool init = true); 333 334 mxArray (mxClassID id, double val); 335 336 mxArray (mxClassID id, mxLogical val); 337 338 mxArray (const char *str); 339 340 mxArray (mwSize m, const char **str); 341 342 mxArray (mxClassID id, mwSize m, mwSize n, mwSize nzmax, 343 mxComplexity flag = mxREAL); 344 345 mxArray (mwSize ndims, const mwSize *dims, int num_keys, const char **keys); 346 347 mxArray (const dim_vector& dv, int num_keys, const char **keys); 348 349 mxArray (mwSize m, mwSize n, int num_keys, const char **keys); 350 351 mxArray (mwSize ndims, const mwSize *dims); 352 353 mxArray (const dim_vector& dv); 354 355 mxArray (mwSize m, mwSize n); 356 dup(void)357 mxArray * dup (void) const 358 { 359 mxArray *retval = rep->as_mxArray (); 360 361 if (retval) 362 retval->set_name (name); 363 else 364 { 365 mxArray_base *new_rep = rep->dup (); 366 367 retval = new mxArray (new_rep, name); 368 } 369 370 return retval; 371 } 372 373 // No copying! 374 375 mxArray (const mxArray&) = delete; 376 377 mxArray& operator = (const mxArray&) = delete; 378 379 ~mxArray (void); 380 is_octave_value(void)381 bool is_octave_value (void) const { return rep->is_octave_value (); } 382 iscell(void)383 int iscell (void) const { return rep->iscell (); } 384 is_char(void)385 int is_char (void) const { return rep->is_char (); } 386 is_class(const char * name_arg)387 int is_class (const char *name_arg) const { return rep->is_class (name_arg); } 388 is_complex(void)389 int is_complex (void) const { return rep->is_complex (); } 390 is_double(void)391 int is_double (void) const { return rep->is_double (); } 392 is_function_handle(void)393 int is_function_handle (void) const { return rep->is_function_handle (); } 394 is_int16(void)395 int is_int16 (void) const { return rep->is_int16 (); } 396 is_int32(void)397 int is_int32 (void) const { return rep->is_int32 (); } 398 is_int64(void)399 int is_int64 (void) const { return rep->is_int64 (); } 400 is_int8(void)401 int is_int8 (void) const { return rep->is_int8 (); } 402 is_logical(void)403 int is_logical (void) const { return rep->is_logical (); } 404 is_numeric(void)405 int is_numeric (void) const { return rep->is_numeric (); } 406 is_single(void)407 int is_single (void) const { return rep->is_single (); } 408 is_sparse(void)409 int is_sparse (void) const { return rep->is_sparse (); } 410 is_struct(void)411 int is_struct (void) const { return rep->is_struct (); } 412 is_uint16(void)413 int is_uint16 (void) const { return rep->is_uint16 (); } 414 is_uint32(void)415 int is_uint32 (void) const { return rep->is_uint32 (); } 416 is_uint64(void)417 int is_uint64 (void) const { return rep->is_uint64 (); } 418 is_uint8(void)419 int is_uint8 (void) const { return rep->is_uint8 (); } 420 is_logical_scalar(void)421 int is_logical_scalar (void) const { return rep->is_logical_scalar (); } 422 is_logical_scalar_true(void)423 int is_logical_scalar_true (void) const 424 { return rep->is_logical_scalar_true (); } 425 get_m(void)426 mwSize get_m (void) const { return rep->get_m (); } 427 get_n(void)428 mwSize get_n (void) const { return rep->get_n (); } 429 get_dimensions(void)430 mwSize * get_dimensions (void) const { return rep->get_dimensions (); } 431 get_number_of_dimensions(void)432 mwSize get_number_of_dimensions (void) const 433 { return rep->get_number_of_dimensions (); } 434 set_m(mwSize m)435 void set_m (mwSize m) { DO_VOID_MUTABLE_METHOD (set_m (m)); } 436 set_n(mwSize n)437 void set_n (mwSize n) { DO_VOID_MUTABLE_METHOD (set_n (n)); } 438 set_dimensions(mwSize * dims_arg,mwSize ndims_arg)439 int set_dimensions (mwSize *dims_arg, mwSize ndims_arg) 440 { DO_MUTABLE_METHOD (int, set_dimensions (dims_arg, ndims_arg)); } 441 get_number_of_elements(void)442 mwSize get_number_of_elements (void) const 443 { return rep->get_number_of_elements (); } 444 isempty(void)445 int isempty (void) const { return get_number_of_elements () == 0; } 446 is_scalar(void)447 bool is_scalar (void) const { return rep->is_scalar (); } 448 get_name(void)449 const char * get_name (void) const { return name; } 450 451 void set_name (const char *name_arg); 452 get_class_id(void)453 mxClassID get_class_id (void) const { return rep->get_class_id (); } 454 get_class_name(void)455 const char * get_class_name (void) const { return rep->get_class_name (); } 456 get_property(mwIndex idx,const char * pname)457 mxArray * get_property (mwIndex idx, const char *pname) const 458 { return rep->get_property (idx, pname); } 459 set_property(mwIndex idx,const char * pname,const mxArray * pval)460 void set_property (mwIndex idx, const char *pname, const mxArray *pval) 461 { rep->set_property (idx, pname, pval); } 462 set_class_name(const char * name_arg)463 void set_class_name (const char *name_arg) 464 { DO_VOID_MUTABLE_METHOD (set_class_name (name_arg)); } 465 get_cell(mwIndex idx)466 mxArray * get_cell (mwIndex idx) const 467 { DO_MUTABLE_METHOD (mxArray *, get_cell (idx)); } 468 set_cell(mwIndex idx,mxArray * val)469 void set_cell (mwIndex idx, mxArray *val) 470 { DO_VOID_MUTABLE_METHOD (set_cell (idx, val)); } 471 get_scalar(void)472 double get_scalar (void) const { return rep->get_scalar (); } 473 get_data(void)474 void * get_data (void) const { DO_MUTABLE_METHOD (void *, get_data ()); } 475 get_imag_data(void)476 void * get_imag_data (void) const 477 { DO_MUTABLE_METHOD (void *, get_imag_data ()); } 478 set_data(void * pr)479 void set_data (void *pr) { DO_VOID_MUTABLE_METHOD (set_data (pr)); } 480 set_imag_data(void * pi)481 void set_imag_data (void *pi) { DO_VOID_MUTABLE_METHOD (set_imag_data (pi)); } 482 get_ir(void)483 mwIndex * get_ir (void) const { DO_MUTABLE_METHOD (mwIndex *, get_ir ()); } 484 get_jc(void)485 mwIndex * get_jc (void) const { DO_MUTABLE_METHOD (mwIndex *, get_jc ()); } 486 get_nzmax(void)487 mwSize get_nzmax (void) const { return rep->get_nzmax (); } 488 set_ir(mwIndex * ir)489 void set_ir (mwIndex *ir) { DO_VOID_MUTABLE_METHOD (set_ir (ir)); } 490 set_jc(mwIndex * jc)491 void set_jc (mwIndex *jc) { DO_VOID_MUTABLE_METHOD (set_jc (jc)); } 492 set_nzmax(mwSize nzmax)493 void set_nzmax (mwSize nzmax) { DO_VOID_MUTABLE_METHOD (set_nzmax (nzmax)); } 494 add_field(const char * key)495 int add_field (const char *key) { DO_MUTABLE_METHOD (int, add_field (key)); } 496 remove_field(int key_num)497 void remove_field (int key_num) 498 { DO_VOID_MUTABLE_METHOD (remove_field (key_num)); } 499 get_field_by_number(mwIndex index,int key_num)500 mxArray * get_field_by_number (mwIndex index, int key_num) const 501 { DO_MUTABLE_METHOD (mxArray *, get_field_by_number (index, key_num)); } 502 set_field_by_number(mwIndex index,int key_num,mxArray * val)503 void set_field_by_number (mwIndex index, int key_num, mxArray *val) 504 { DO_VOID_MUTABLE_METHOD (set_field_by_number (index, key_num, val)); } 505 get_number_of_fields(void)506 int get_number_of_fields (void) const { return rep->get_number_of_fields (); } 507 get_field_name_by_number(int key_num)508 const char * get_field_name_by_number (int key_num) const 509 { DO_MUTABLE_METHOD (const char*, get_field_name_by_number (key_num)); } 510 get_field_number(const char * key)511 int get_field_number (const char *key) const 512 { DO_MUTABLE_METHOD (int, get_field_number (key)); } 513 get_string(char * buf,mwSize buflen)514 int get_string (char *buf, mwSize buflen) const 515 { return rep->get_string (buf, buflen); } 516 array_to_string(void)517 char * array_to_string (void) const { return rep->array_to_string (); } 518 calc_single_subscript(mwSize nsubs,mwIndex * subs)519 mwIndex calc_single_subscript (mwSize nsubs, mwIndex *subs) const 520 { return rep->calc_single_subscript (nsubs, subs); } 521 get_element_size(void)522 std::size_t get_element_size (void) const { return rep->get_element_size (); } 523 mutation_needed(void)524 bool mutation_needed (void) const { return rep->mutation_needed (); } 525 mutate(void)526 mxArray * mutate (void) const { return rep->mutate (); } 527 528 static void * malloc (std::size_t n); 529 530 static void * calloc (std::size_t n, std::size_t t); 531 strsave(const char * str)532 static char * strsave (const char *str) 533 { 534 char *retval = nullptr; 535 536 if (str) 537 { 538 mwSize sz = sizeof (mxChar) * (strlen (str) + 1); 539 540 retval = static_cast<char *> (mxArray::malloc (sz)); 541 542 if (retval) 543 strcpy (retval, str); 544 } 545 546 return retval; 547 } 548 549 static octave_value 550 as_octave_value (const mxArray *ptr, bool null_is_empty = true); 551 552 octave_value as_octave_value (void) const; 553 554 private: 555 556 mutable mxArray_base *rep; 557 558 char *name; 559 mxArray(mxArray_base * r,const char * n)560 mxArray (mxArray_base *r, const char *n) 561 : rep (r), name (mxArray::strsave (n)) { } 562 563 void maybe_mutate (void) const; 564 }; 565 566 #undef DO_MUTABLE_METHOD 567 #undef DO_VOID_MUTABLE_METHOD 568 569 #endif 570 #endif 571