Mercurial > hg > octave-lyh
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 |