GNU Octave  4.4.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
ls-oct-binary.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1996-2018 John W. Eaton
4 
5 This file is part of Octave.
6 
7 Octave is free software: you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <https://www.gnu.org/licenses/>.
20 
21 */
22 
23 #if defined (HAVE_CONFIG_H)
24 # include "config.h"
25 #endif
26 
27 #include <iostream>
28 #include <string>
29 
30 #include "byte-swap.h"
31 #include "data-conv.h"
32 #include "file-ops.h"
33 #include "glob-match.h"
34 #include "lo-mappers.h"
35 #include "mach-info.h"
36 #include "oct-env.h"
37 #include "oct-locbuf.h"
38 #include "oct-time.h"
39 
40 #include "defun.h"
41 #include "error.h"
42 #include "errwarn.h"
43 #include "interpreter-private.h"
44 #include "load-save.h"
45 #include "ls-oct-binary.h"
46 #include "ls-utils.h"
47 #include "ov-cell.h"
48 #include "ov.h"
49 #include "pager.h"
50 #include "pt-exp.h"
51 #include "sysdep.h"
52 #include "utils.h"
53 #include "variables.h"
54 #include "version.h"
55 
56 // Extract one value (scalar, matrix, string, etc.) from stream IS and
57 // place it in TC, returning the name of the variable. If the value
58 // is tagged as global in the file, return TRUE in GLOBAL. If SWAP
59 // is TRUE, swap bytes after reading.
60 //
61 // The data is expected to be in the following format:
62 //
63 // Header (one per file):
64 // =====================
65 //
66 // object type bytes
67 // ------ ---- -----
68 // magic number string 10
69 //
70 // float format integer 1
71 //
72 //
73 // Data (one set for each item):
74 // ============================
75 //
76 // object type bytes
77 // ------ ---- -----
78 // name_length integer 4
79 //
80 // name string name_length
81 //
82 // doc_length integer 4
83 //
84 // doc string doc_length
85 //
86 // global flag integer 1
87 //
88 // data type char 1
89 //
90 // In general "data type" is 255, and in that case the next arguments
91 // in the data set are
92 //
93 // object type bytes
94 // ------ ---- -----
95 // type_length integer 4
96 //
97 // type string type_length
98 //
99 // The string "type" is then used with octave::type_info::lookup_type
100 // to create an octave_value of the correct type. The specific load/save
101 // function is then called.
102 //
103 // For backward compatibility "data type" can also be a value between 1
104 // and 7, where this defines a hardcoded octave_value of the type
105 //
106 // data type octave_value
107 // --------- ------------
108 // 1 scalar
109 // 2 matrix
110 // 3 complex scalar
111 // 4 complex matrix
112 // 5 string (old style storage)
113 // 6 range
114 // 7 string
115 //
116 // Except for "data type" equal 5 that requires special treatment, these
117 // old style "data type" value also cause the specific load/save functions
118 // to be called. FILENAME is used for error messages.
119 
121 read_binary_data (std::istream& is, bool swap,
123  const std::string& filename, bool& global,
124  octave_value& tc, std::string& doc)
125 {
127 
128  unsigned char tmp = 0;
129 
130  int32_t name_len = 0;
131  int32_t doc_len = 0;
132 
133  doc.clear ();
134 
135  // We expect to fail here, at the beginning of a record, so not
136  // being able to read another name should not result in an error.
137 
138  is.read (reinterpret_cast<char *> (&name_len), 4);
139  if (! is)
140  return retval;
141  if (swap)
142  swap_bytes<4> (&name_len);
143 
144  {
145  OCTAVE_LOCAL_BUFFER (char, name, name_len+1);
146  name[name_len] = '\0';
147  if (! is.read (reinterpret_cast<char *> (name), name_len))
148  error ("load: trouble reading binary file '%s'", filename.c_str ());
149  retval = name;
150  }
151 
152  is.read (reinterpret_cast<char *> (&doc_len), 4);
153  if (! is)
154  error ("load: trouble reading binary file '%s'", filename.c_str ());
155  if (swap)
156  swap_bytes<4> (&doc_len);
157 
158  {
159  OCTAVE_LOCAL_BUFFER (char, tdoc, doc_len+1);
160  tdoc[doc_len] = '\0';
161  if (! is.read (reinterpret_cast<char *> (tdoc), doc_len))
162  error ("load: trouble reading binary file '%s'", filename.c_str ());
163  doc = tdoc;
164  }
165 
166  if (! is.read (reinterpret_cast<char *> (&tmp), 1))
167  error ("load: trouble reading binary file '%s'", filename.c_str ());
168  global = (tmp ? 1 : 0);
169 
170  tmp = 0;
171  if (! is.read (reinterpret_cast<char *> (&tmp), 1))
172  error ("load: trouble reading binary file '%s'", filename.c_str ());
173 
174  octave::type_info& type_info
175  = octave::__get_type_info__ ("read_binary_data");
176 
177  // All cases except 255 kept for backwards compatibility
178  switch (tmp)
179  {
180  case 1:
181  tc = type_info.lookup_type ("scalar");
182  break;
183 
184  case 2:
185  tc = type_info.lookup_type ("matrix");
186  break;
187 
188  case 3:
189  tc = type_info.lookup_type ("complex scalar");
190  break;
191 
192  case 4:
193  tc = type_info.lookup_type ("complex matrix");
194  break;
195 
196  case 5:
197  {
198  // FIXME:
199  // This is cruft, since its for a save type that is old.
200  // Maybe this is taking backward compatibility too far!
201  int32_t len;
202  if (! is.read (reinterpret_cast<char *> (&len), 4))
203  error ("load: trouble reading binary file '%s'", filename.c_str ());
204  if (swap)
205  swap_bytes<4> (&len);
206  OCTAVE_LOCAL_BUFFER (char, s, len+1);
207  if (! is.read (reinterpret_cast<char *> (s), len))
208  error ("load: trouble reading binary file '%s'", filename.c_str ());
209  s[len] = '\0';
210  tc = s;
211 
212  // Early return, since don't want rest of this function
213  return retval;
214  }
215  break;
216 
217  case 6:
218  tc = type_info.lookup_type ("range");
219  break;
220 
221  case 7:
222  tc = type_info.lookup_type ("string");
223  break;
224 
225  case 255:
226  {
227  // Read the saved variable type
228  int32_t len;
229  if (! is.read (reinterpret_cast<char *> (&len), 4))
230  error ("load: trouble reading binary file '%s'", filename.c_str ());
231  if (swap)
232  swap_bytes<4> (&len);
233  OCTAVE_LOCAL_BUFFER (char, s, len+1);
234  if (! is.read (s, len))
235  error ("load: trouble reading binary file '%s'", filename.c_str ());
236  s[len] = '\0';
237  std::string typ = s;
238  tc = type_info.lookup_type (typ);
239  }
240  break;
241  default:
242  error ("load: trouble reading binary file '%s'", filename.c_str ());
243  break;
244  }
245 
246  if (! tc.load_binary (is, swap, fmt))
247  error ("load: trouble reading binary file '%s'", filename.c_str ());
248 
249  return retval;
250 }
251 
252 // Save the data from TC along with the corresponding NAME, help
253 // string DOC, and global flag MARK_AS_GLOBAL on stream OS in the
254 // binary format described above for read_binary_data.
255 
256 bool
257 save_binary_data (std::ostream& os, const octave_value& tc,
258  const std::string& name, const std::string& doc,
259  bool mark_global, bool save_as_floats)
260 {
261  int32_t name_len = name.length ();
262 
263  os.write (reinterpret_cast<char *> (&name_len), 4);
264  os << name;
265 
266  int32_t doc_len = doc.length ();
267 
268  os.write (reinterpret_cast<char *> (&doc_len), 4);
269  os << doc;
270 
271  unsigned char tmp;
272 
273  tmp = mark_global;
274  os.write (reinterpret_cast<char *> (&tmp), 1);
275 
276  // 255 flags the new binary format
277  tmp = 255;
278  os.write (reinterpret_cast<char *> (&tmp), 1);
279 
280  // Write the string corresponding to the octave_value type
281  std::string typ = tc.type_name ();
282  int32_t len = typ.length ();
283  os.write (reinterpret_cast<char *> (&len), 4);
284  const char *btmp = typ.data ();
285  os.write (btmp, len);
286 
287  // The octave_value of tc is const. Make a copy...
288  octave_value val = tc;
289 
290  // Call specific save function
291  bool success = val.save_binary (os, save_as_floats);
292 
293  return (os && success);
294 }
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
octave_value lookup_type(const std::string &nm)
Definition: ov-typeinfo.cc:476
identity matrix If supplied two scalar respectively For allows like xample val
Definition: data.cc:4986
void error(const char *fmt,...)
Definition: error.cc:578
std::string filename
Definition: urlwrite.cc:121
s
Definition: file-io.cc:2729
bool swap
Definition: load-save.cc:738
nd deftypefn *std::string name
Definition: sysdep.cc:647
void swap_bytes< 4 >(void *ptr)
Definition: byte-swap.h:60
type_info & __get_type_info__(const std::string &who)
bool save_as_floats
Definition: load-save.cc:1617
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_value retval
Definition: data.cc:6246
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
Definition: oct-locbuf.h:41
write the output to stdout if nargout is
Definition: load-save.cc:1612
bool load_binary(std::istream &is, bool swap, octave::mach_info::float_format fmt)
Definition: ov.h:1341
std::string type_name(void) const
Definition: ov.h:1289
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
octave::stream os
Definition: file-io.cc:627
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)