comparison src/ls-oct-binary.cc @ 4634:79fe96966ca0

[project @ 2003-11-19 21:22:39 by jwe]
author jwe
date Wed, 19 Nov 2003 21:23:19 +0000
parents
children e95c86d48732
comparison
equal deleted inserted replaced
4633:d95dd6ae89fd 4634:79fe96966ca0
1 /*
2
3 Copyright (C) 1996, 1997 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 the
9 Free Software Foundation; either version 2, or (at your option) any
10 later version.
11
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 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, write to the Free
19 Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <cfloat>
28 #include <cstring>
29 #include <cctype>
30
31 #include <fstream>
32 #include <iomanip>
33 #include <iostream>
34 #include <memory>
35 #include <string>
36
37 #include "byte-swap.h"
38 #include "data-conv.h"
39 #include "file-ops.h"
40 #include "glob-match.h"
41 #include "lo-mappers.h"
42 #include "lo-sstream.h"
43 #include "mach-info.h"
44 #include "oct-env.h"
45 #include "oct-time.h"
46 #include "quit.h"
47 #include "str-vec.h"
48
49 #include "Cell.h"
50 #include "defun.h"
51 #include "error.h"
52 #include "gripes.h"
53 #include "load-save.h"
54 #include "oct-obj.h"
55 #include "oct-map.h"
56 #include "ov-cell.h"
57 #include "pager.h"
58 #include "pt-exp.h"
59 #include "symtab.h"
60 #include "sysdep.h"
61 #include "unwind-prot.h"
62 #include "utils.h"
63 #include "variables.h"
64 #include "version.h"
65 #include "dMatrix.h"
66
67 #include "ls-utils.h"
68 #include "ls-oct-binary.h"
69
70 // Extract one value (scalar, matrix, string, etc.) from stream IS and
71 // place it in TC, returning the name of the variable. If the value
72 // is tagged as global in the file, return TRUE in GLOBAL. If SWAP
73 // is TRUE, swap bytes after reading.
74 //
75 // The data is expected to be in the following format:
76 //
77 // Header (one per file):
78 // =====================
79 //
80 // object type bytes
81 // ------ ---- -----
82 // magic number string 10
83 //
84 // float format integer 1
85 //
86 //
87 // Data (one set for each item):
88 // ============================
89 //
90 // object type bytes
91 // ------ ---- -----
92 // name_length integer 4
93 //
94 // name string name_length
95 //
96 // doc_length integer 4
97 //
98 // doc string doc_length
99 //
100 // global flag integer 1
101 //
102 // data type integer 1
103 //
104 // data (one of):
105 //
106 // scalar:
107 // data real 8
108 //
109 // complex scalar:
110 // data complex 16
111 //
112 // matrix:
113 // rows integer 4
114 // columns integer 4
115 // data real r*c*8
116 //
117 // complex matrix:
118 // rows integer 4
119 // columns integer 4
120 // data complex r*c*16
121 //
122 // string:
123 // length int 4
124 // data string length
125 //
126 // range:
127 // base real 8
128 // limit real 8
129 // increment real 8
130 //
131 // string array
132 // elements int 4
133 //
134 // for each element:
135 // length int 4
136 // data string length
137 //
138 // FILENAME is used for error messages.
139
140 std::string
141 read_binary_data (std::istream& is, bool swap,
142 oct_mach_info::float_format fmt,
143 const std::string& filename, bool& global,
144 octave_value& tc, std::string& doc)
145 {
146 std::string retval;
147
148 char tmp = 0;
149
150 FOUR_BYTE_INT name_len = 0;
151 FOUR_BYTE_INT doc_len = 0;
152
153 doc.resize (0);
154
155 // We expect to fail here, at the beginning of a record, so not
156 // being able to read another name should not result in an error.
157
158 is.read (X_CAST (char *, &name_len), 4);
159 if (! is)
160 return retval;
161 if (swap)
162 swap_4_bytes (X_CAST (char *, &name_len));
163
164 {
165 OCTAVE_LOCAL_BUFFER (char, name, name_len+1);
166 name[name_len] = '\0';
167 if (! is.read (X_CAST (char *, name), name_len))
168 goto data_read_error;
169 retval = name;
170 }
171
172 is.read (X_CAST (char *, &doc_len), 4);
173 if (! is)
174 goto data_read_error;
175 if (swap)
176 swap_4_bytes (X_CAST (char *, &doc_len));
177
178 {
179 OCTAVE_LOCAL_BUFFER (char, tdoc, doc_len+1);
180 tdoc[doc_len] = '\0';
181 if (! is.read (X_CAST (char *, tdoc), doc_len))
182 goto data_read_error;
183 doc = tdoc;
184 }
185
186 if (! is.read (X_CAST (char *, &tmp), 1))
187 goto data_read_error;
188 global = tmp ? 1 : 0;
189
190 tmp = 0;
191 if (! is.read (X_CAST (char *, &tmp), 1))
192 goto data_read_error;
193
194 switch (tmp)
195 {
196 case 1:
197 {
198 if (! is.read (X_CAST (char *, &tmp), 1))
199 goto data_read_error;
200 double dtmp;
201 read_doubles (is, &dtmp, X_CAST (save_type, tmp), 1, swap, fmt);
202 if (error_state || ! is)
203 goto data_read_error;
204 tc = dtmp;
205 }
206 break;
207
208 case 2:
209 {
210 FOUR_BYTE_INT nr, nc;
211 if (! is.read (X_CAST (char *, &nr), 4))
212 goto data_read_error;
213 if (swap)
214 swap_4_bytes (X_CAST (char *, &nr));
215 if (! is.read (X_CAST (char *, &nc), 4))
216 goto data_read_error;
217 if (swap)
218 swap_4_bytes (X_CAST (char *, &nc));
219 if (! is.read (X_CAST (char *, &tmp), 1))
220 goto data_read_error;
221 Matrix m (nr, nc);
222 double *re = m.fortran_vec ();
223 int len = nr * nc;
224 read_doubles (is, re, X_CAST (save_type, tmp), len, swap, fmt);
225 if (error_state || ! is)
226 goto data_read_error;
227 tc = m;
228 }
229 break;
230
231 case 3:
232 {
233 if (! is.read (X_CAST (char *, &tmp), 1))
234 goto data_read_error;
235 Complex ctmp;
236 read_doubles (is, X_CAST (double *, &ctmp),
237 X_CAST (save_type, tmp), 2, swap, fmt);
238 if (error_state || ! is)
239 goto data_read_error;
240 tc = ctmp;
241 }
242 break;
243
244 case 4:
245 {
246 FOUR_BYTE_INT nr, nc;
247 if (! is.read (X_CAST (char *, &nr), 4))
248 goto data_read_error;
249 if (swap)
250 swap_4_bytes (X_CAST (char *, &nr));
251 if (! is.read (X_CAST (char *, &nc), 4))
252 goto data_read_error;
253 if (swap)
254 swap_4_bytes (X_CAST (char *, &nc));
255 if (! is.read (X_CAST (char *, &tmp), 1))
256 goto data_read_error;
257 ComplexMatrix m (nr, nc);
258 Complex *im = m.fortran_vec ();
259 int len = nr * nc;
260 read_doubles (is, X_CAST (double *, im),
261 X_CAST (save_type, tmp), 2*len, swap, fmt);
262 if (error_state || ! is)
263 goto data_read_error;
264 tc = m;
265 }
266 break;
267
268 case 5:
269 {
270 FOUR_BYTE_INT len;
271 if (! is.read (X_CAST (char *, &len), 4))
272 goto data_read_error;
273 if (swap)
274 swap_4_bytes (X_CAST (char *, &len));
275 OCTAVE_LOCAL_BUFFER (char, s, len+1);
276 if (! is.read (X_CAST (char *, s), len))
277 goto data_read_error;
278 s[len] = '\0';
279 tc = s;
280 }
281 break;
282
283 case 6:
284 {
285 if (! is.read (X_CAST (char *, &tmp), 1))
286 goto data_read_error;
287 double bas, lim, inc;
288 if (! is.read (X_CAST (char *, &bas), 8))
289 goto data_read_error;
290 if (swap)
291 swap_8_bytes (X_CAST (char *, &bas));
292 if (! is.read (X_CAST (char *, &lim), 8))
293 goto data_read_error;
294 if (swap)
295 swap_8_bytes (X_CAST (char *, &lim));
296 if (! is.read (X_CAST (char *, &inc), 8))
297 goto data_read_error;
298 if (swap)
299 swap_8_bytes (X_CAST (char *, &inc));
300 Range r (bas, lim, inc);
301 tc = r;
302 }
303 break;
304
305 case 7:
306 {
307 FOUR_BYTE_INT elements;
308 if (! is.read (X_CAST (char *, &elements), 4))
309 goto data_read_error;
310 if (swap)
311 swap_4_bytes (X_CAST (char *, &elements));
312 charMatrix chm (elements, 0);
313 int max_len = 0;
314 for (int i = 0; i < elements; i++)
315 {
316 FOUR_BYTE_INT len;
317 if (! is.read (X_CAST (char *, &len), 4))
318 goto data_read_error;
319 if (swap)
320 swap_4_bytes (X_CAST (char *, &len));
321 OCTAVE_LOCAL_BUFFER (char, btmp, len+1);
322 if (! is.read (X_CAST (char *, btmp), len))
323 goto data_read_error;
324 if (len > max_len)
325 {
326 max_len = len;
327 chm.resize (elements, max_len, 0);
328 }
329 btmp [len] = '\0';
330 chm.insert (btmp, i, 0);
331 }
332 tc = octave_value (chm, true);
333 }
334 break;
335
336 default:
337 data_read_error:
338 error ("load: trouble reading binary file `%s'", filename.c_str ());
339 break;
340 }
341
342 return retval;
343 }
344
345 // Save the data from TC along with the corresponding NAME, help
346 // string DOC, and global flag MARK_AS_GLOBAL on stream OS in the
347 // binary format described above for read_binary_data.
348
349 bool
350 save_binary_data (std::ostream& os, const octave_value& tc,
351 const std::string& name, const std::string& doc,
352 bool mark_as_global, bool save_as_floats)
353 {
354 FOUR_BYTE_INT name_len = name.length ();
355
356 os.write (X_CAST (char *, &name_len), 4);
357 os << name;
358
359 FOUR_BYTE_INT doc_len = doc.length ();
360
361 os.write (X_CAST (char *, &doc_len), 4);
362 os << doc;
363
364 char tmp;
365
366 tmp = mark_as_global;
367 os.write (X_CAST (char *, &tmp), 1);
368
369 if (tc.is_string ())
370 {
371 tmp = 7;
372 os.write (X_CAST (char *, &tmp), 1);
373 FOUR_BYTE_INT nr = tc.rows ();
374 os.write (X_CAST (char *, &nr), 4);
375 charMatrix chm = tc.char_matrix_value ();
376 for (int i = 0; i < nr; i++)
377 {
378 FOUR_BYTE_INT len = chm.cols ();
379 os.write (X_CAST (char *, &len), 4);
380 std::string tstr = chm.row_as_string (i);
381 const char *btmp = tstr.data ();
382 os.write (X_CAST (char *, btmp), len);
383 }
384 }
385 else if (tc.is_range ())
386 {
387 tmp = 6;
388 os.write (X_CAST (char *, &tmp), 1);
389 tmp = (char) LS_DOUBLE;
390 os.write (X_CAST (char *, &tmp), 1);
391 Range r = tc.range_value ();
392 double bas = r.base ();
393 double lim = r.limit ();
394 double inc = r.inc ();
395 os.write (X_CAST (char *, &bas), 8);
396 os.write (X_CAST (char *, &lim), 8);
397 os.write (X_CAST (char *, &inc), 8);
398 }
399 else if (tc.is_real_scalar ())
400 {
401 tmp = 1;
402 os.write (X_CAST (char *, &tmp), 1);
403 tmp = (char) LS_DOUBLE;
404 os.write (X_CAST (char *, &tmp), 1);
405 double dtmp = tc.double_value ();
406 os.write (X_CAST (char *, &dtmp), 8);
407 }
408 else if (tc.is_real_matrix ())
409 {
410 tmp = 2;
411 os.write (X_CAST (char *, &tmp), 1);
412 Matrix m = tc.matrix_value ();
413 FOUR_BYTE_INT nr = m.rows ();
414 FOUR_BYTE_INT nc = m.columns ();
415 os.write (X_CAST (char *, &nr), 4);
416 os.write (X_CAST (char *, &nc), 4);
417 int len = nr * nc;
418 save_type st = LS_DOUBLE;
419 if (save_as_floats)
420 {
421 if (m.too_large_for_float ())
422 {
423 warning ("save: some values too large to save as floats --");
424 warning ("save: saving as doubles instead");
425 }
426 else
427 st = LS_FLOAT;
428 }
429 else if (len > 8192) // XXX FIXME XXX -- make this configurable.
430 {
431 double max_val, min_val;
432 if (m.all_integers (max_val, min_val))
433 st = get_save_type (max_val, min_val);
434 }
435 const double *mtmp = m.data ();
436 write_doubles (os, mtmp, st, len);
437 }
438 else if (tc.is_complex_scalar ())
439 {
440 tmp = 3;
441 os.write (X_CAST (char *, &tmp), 1);
442 tmp = (char) LS_DOUBLE;
443 os.write (X_CAST (char *, &tmp), 1);
444 Complex ctmp = tc.complex_value ();
445 os.write (X_CAST (char *, &ctmp), 16);
446 }
447 else if (tc.is_complex_matrix ())
448 {
449 tmp = 4;
450 os.write (X_CAST (char *, &tmp), 1);
451 ComplexMatrix m = tc.complex_matrix_value ();
452 FOUR_BYTE_INT nr = m.rows ();
453 FOUR_BYTE_INT nc = m.columns ();
454 os.write (X_CAST (char *, &nr), 4);
455 os.write (X_CAST (char *, &nc), 4);
456 int len = nr * nc;
457 save_type st = LS_DOUBLE;
458 if (save_as_floats)
459 {
460 if (m.too_large_for_float ())
461 {
462 warning ("save: some values too large to save as floats --");
463 warning ("save: saving as doubles instead");
464 }
465 else
466 st = LS_FLOAT;
467 }
468 else if (len > 4096) // XXX FIXME XXX -- make this configurable.
469 {
470 double max_val, min_val;
471 if (m.all_integers (max_val, min_val))
472 st = get_save_type (max_val, min_val);
473 }
474 const Complex *mtmp = m.data ();
475 write_doubles (os, X_CAST (const double *, mtmp), st, 2*len);
476 }
477 else
478 gripe_wrong_type_arg ("save", tc, false);
479
480 return os;
481 }
482
483 /*
484 ;;; Local Variables: ***
485 ;;; mode: C++ ***
486 ;;; End: ***
487 */
488