1 /* 2 3 Copyright (C) 2016-2019 Olaf Till <i7tiol@t-online.de> 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 3 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; If not, see <http://www.gnu.org/licenses/>. 17 18 */ 19 20 #include <octave/oct.h> 21 22 #include <octave/load-save.h> 23 24 #include <octave/byte-swap.h> 25 26 #include <octave/ls-mat4.h> 27 28 #include "error-helpers.h" 29 30 DEFUN_DLD (bytea2var, args, nout, 31 "-*- texinfo -*-\n\ 32 @deftypefn {Loadable Function} {} bytea2var (@var{value}, @dots{})\n\ 33 Restore variable values from uint8 arrays generated with @code{var2bytea}.\n\ 34 \n\ 35 Returns as many output variables as input variables are given.\n\ 36 \n\ 37 @seealso{var2bytea}\n\ 38 @end deftypefn") 39 { 40 std::string fname ("bytea2var"); 41 42 octave_idx_type nargs = args.length (); 43 44 octave_idx_type nvars = nout < nargs ? nout : nargs; 45 46 octave_value_list retval (nvars); 47 48 bool err = false; 49 50 octave_idx_type i; 51 52 for (i = 0; i < nvars; i++) 53 { 54 uint8NDArray m; 55 56 octave_value val; 57 58 CHECK_ERROR (m = args(i).uint8_array_value (), retval, 59 "%s: could not convert argument %li to uint8 array", 60 fname.c_str (), i + 1); 61 62 octave_idx_type nel = m.numel (); 63 64 std::string s ((char *) m.fortran_vec (), nel); 65 66 std::istringstream is (s); 67 68 bool swap; 69 OCTAVE__MACH_INFO::float_format flt_fmt; 70 71 /* 72 slightly changed from load-save.cc (read_binary_file_header()) 73 to reduce storage size 74 */ 75 76 const int magic_len = 2; 77 char magic[magic_len+1]; 78 is.read (magic, magic_len); 79 magic[magic_len] = '\0'; 80 81 if (strncmp (magic, "1L", magic_len) == 0) 82 swap = OCTAVE__MACH_INFO::words_big_endian (); 83 else if (strncmp (magic, "1B", magic_len) == 0) 84 swap = ! OCTAVE__MACH_INFO::words_big_endian (); 85 else 86 { 87 error ("%s: could not read binary header", fname.c_str ()); 88 89 return retval; 90 } 91 92 char tmp = 0; 93 is.read (&tmp, 1); 94 95 flt_fmt = mopt_digit_to_float_format (tmp); 96 97 if (flt_fmt == OCTAVE__MACH_INFO::flt_fmt_unknown) 98 { 99 error ("%s: unrecognized binary format", fname.c_str ()); 100 101 return retval; 102 } 103 104 int32_t len; 105 if (! is.read (reinterpret_cast<char *> (&len), 4)) 106 { 107 err = true; 108 109 break; 110 } 111 112 if (swap) 113 swap_bytes<4> (&len); 114 115 { 116 OCTAVE_LOCAL_BUFFER (char, buf, len+1); 117 if (! is.read (buf, len)) 118 { 119 err = true; 120 121 break; 122 } 123 buf[len] = '\0'; 124 std::string typ (buf); 125 val = octave_value_typeinfo::lookup_type (typ); 126 } 127 128 if (! val.load_binary (is, swap, flt_fmt)) 129 { 130 err = true; 131 132 break; 133 } 134 135 retval(i) = val; 136 } 137 138 if (err) 139 error ("%s: could not load variable %li", fname.c_str (), i + 1); 140 141 return retval; 142 } 143