2376
|
1 /* |
|
2 |
2847
|
3 Copyright (C) 1996, 1997 John W. Eaton |
2376
|
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 |
4192
|
23 #if defined (__GNUG__) && defined (USE_PRAGMA_INTERFACE_IMPLEMENTATION) |
2376
|
24 #pragma implementation |
|
25 #endif |
|
26 |
|
27 #ifdef HAVE_CONFIG_H |
|
28 #include <config.h> |
|
29 #endif |
|
30 |
3503
|
31 #include <iostream> |
2901
|
32 |
2376
|
33 #include "lo-ieee.h" |
|
34 #include "mx-base.h" |
|
35 |
2407
|
36 #include "oct-obj.h" |
2376
|
37 #include "ops.h" |
|
38 #include "ov-re-mat.h" |
|
39 #include "ov-str-mat.h" |
|
40 #include "gripes.h" |
|
41 #include "pr-output.h" |
3836
|
42 #include "pt-mat.h" |
2376
|
43 |
4687
|
44 #include "byte-swap.h" |
|
45 #include "ls-oct-ascii.h" |
|
46 #include "ls-hdf5.h" |
|
47 #include "ls-utils.h" |
|
48 |
3219
|
49 DEFINE_OCTAVE_ALLOCATOR (octave_char_matrix_str); |
2376
|
50 |
4612
|
51 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_char_matrix_str, "string", "char"); |
2376
|
52 |
|
53 static octave_value * |
|
54 default_numeric_conversion_function (const octave_value& a) |
|
55 { |
|
56 CAST_CONV_ARG (const octave_char_matrix_str&); |
|
57 |
4668
|
58 NDArray nda = v.array_value (true); |
3203
|
59 |
4668
|
60 return error_state ? 0 : new octave_matrix (nda); |
2376
|
61 } |
|
62 |
2427
|
63 type_conv_fcn |
2376
|
64 octave_char_matrix_str::numeric_conversion_function (void) const |
|
65 { |
|
66 return default_numeric_conversion_function; |
|
67 } |
|
68 |
|
69 octave_value |
3933
|
70 octave_char_matrix_str::do_index_op (const octave_value_list& idx, |
|
71 int resize_ok) |
2407
|
72 { |
|
73 octave_value retval; |
|
74 |
|
75 int len = idx.length (); |
|
76 |
|
77 switch (len) |
|
78 { |
|
79 case 2: |
|
80 { |
|
81 idx_vector i = idx (0).index_vector (); |
|
82 idx_vector j = idx (1).index_vector (); |
|
83 |
4513
|
84 retval = octave_value (charNDArray (matrix.index (i, j, resize_ok)), |
3933
|
85 true); |
2407
|
86 } |
|
87 break; |
|
88 |
|
89 case 1: |
|
90 { |
|
91 idx_vector i = idx (0).index_vector (); |
|
92 |
4513
|
93 retval = octave_value (charNDArray (matrix.index (i, resize_ok)), |
|
94 true); |
2407
|
95 } |
|
96 break; |
|
97 |
|
98 default: |
4513
|
99 { |
|
100 Array<idx_vector> idx_vec (len); |
|
101 |
|
102 for (int i = 0; i < len; i++) |
|
103 idx_vec(i) = idx(i).index_vector (); |
|
104 |
|
105 retval = octave_value (charNDArray (matrix.index (idx_vec, resize_ok)), |
|
106 true); |
|
107 } |
2407
|
108 break; |
|
109 } |
|
110 |
|
111 return retval; |
|
112 } |
|
113 |
|
114 void |
|
115 octave_char_matrix_str::assign (const octave_value_list& idx, |
|
116 const charMatrix& rhs) |
|
117 { |
|
118 int len = idx.length (); |
|
119 |
2571
|
120 // XXX FIXME XXX |
|
121 charMatrix tmp = rhs; |
|
122 if (tmp.rows () == 1 && tmp.columns () == 0) |
|
123 tmp.resize (0, 0); |
|
124 |
4513
|
125 for (int i = 0; i < len; i++) |
|
126 matrix.set_index (idx(i).index_vector ()); |
2407
|
127 |
4513
|
128 ::assign (matrix, tmp, Vstring_fill_char); |
2407
|
129 } |
|
130 |
2376
|
131 bool |
|
132 octave_char_matrix_str::valid_as_scalar_index (void) const |
|
133 { |
|
134 bool retval = false; |
|
135 error ("octave_char_matrix_str::valid_as_scalar_index(): not implemented"); |
|
136 return retval; |
|
137 } |
|
138 |
4668
|
139 #define CHAR_MATRIX_CONV(T, INIT, TNAME, FCN) \ |
|
140 T retval INIT; \ |
|
141 \ |
|
142 if (! force_string_conv) \ |
|
143 gripe_invalid_conversion ("string", TNAME); \ |
|
144 else \ |
|
145 { \ |
|
146 if (Vwarn_str_to_num) \ |
|
147 gripe_implicit_conversion ("string", TNAME); \ |
|
148 \ |
|
149 retval = octave_char_matrix::FCN (); \ |
|
150 } \ |
|
151 \ |
|
152 return retval |
|
153 |
4643
|
154 double |
|
155 octave_char_matrix_str::double_value (bool force_string_conv) const |
|
156 { |
4668
|
157 CHAR_MATRIX_CONV (double, = 0, "real scalar", double_value); |
|
158 } |
4643
|
159 |
4668
|
160 Complex |
|
161 octave_char_matrix_str::complex_value (bool force_string_conv) const |
|
162 { |
|
163 CHAR_MATRIX_CONV (Complex, = 0, "complex scalar", complex_value); |
4643
|
164 } |
|
165 |
2376
|
166 Matrix |
|
167 octave_char_matrix_str::matrix_value (bool force_string_conv) const |
|
168 { |
4668
|
169 CHAR_MATRIX_CONV (Matrix, , "real matrix", matrix_value); |
|
170 } |
|
171 |
|
172 ComplexMatrix |
|
173 octave_char_matrix_str::complex_matrix_value (bool force_string_conv) const |
|
174 { |
|
175 CHAR_MATRIX_CONV (ComplexMatrix, , "complex matrix", complex_matrix_value); |
|
176 } |
2376
|
177 |
4668
|
178 NDArray |
|
179 octave_char_matrix_str::array_value (bool force_string_conv) const |
|
180 { |
|
181 CHAR_MATRIX_CONV (NDArray, , "real N-d array", array_value); |
|
182 } |
2376
|
183 |
4668
|
184 ComplexNDArray |
|
185 octave_char_matrix_str::complex_array_value (bool force_string_conv) const |
|
186 { |
|
187 CHAR_MATRIX_CONV (ComplexNDArray, , "complex N-d array", |
|
188 complex_array_value); |
2376
|
189 } |
|
190 |
2493
|
191 string_vector |
4457
|
192 octave_char_matrix_str::all_strings (bool, bool) const |
2376
|
193 { |
4513
|
194 string_vector retval; |
|
195 |
|
196 if (matrix.ndims () == 2) |
|
197 { |
|
198 charMatrix chm = matrix.matrix_value (); |
|
199 |
|
200 int n = chm.rows (); |
2493
|
201 |
4513
|
202 retval.resize (n); |
2493
|
203 |
4513
|
204 for (int i = 0; i < n; i++) |
|
205 retval[i] = chm.row_as_string (i, true); |
|
206 } |
|
207 else |
|
208 error ("invalid conversion of charNDArray to string_vector"); |
2493
|
209 |
|
210 return retval; |
2376
|
211 } |
|
212 |
3536
|
213 std::string |
4457
|
214 octave_char_matrix_str::string_value (bool) const |
2376
|
215 { |
4513
|
216 std::string retval; |
|
217 |
|
218 if (matrix.ndims () == 2) |
|
219 { |
|
220 charMatrix chm = matrix.matrix_value (); |
|
221 |
|
222 retval = chm.row_as_string (0); // XXX FIXME??? XXX |
|
223 } |
|
224 else |
|
225 error ("invalid conversion of charNDArray to string"); |
|
226 |
|
227 return retval; |
2376
|
228 } |
|
229 |
|
230 void |
3523
|
231 octave_char_matrix_str::print_raw (std::ostream& os, bool pr_as_read_syntax) const |
2376
|
232 { |
3219
|
233 octave_print_internal (os, matrix, pr_as_read_syntax, |
|
234 current_print_indent_level (), true); |
2376
|
235 } |
|
236 |
4687
|
237 bool |
|
238 octave_char_matrix_str::save_ascii (std::ostream& os, |
|
239 bool& /* infnan_warned */, |
|
240 bool /* strip_nan_and_inf */) |
|
241 { |
|
242 charMatrix chm = char_matrix_value (); |
|
243 int elements = chm.rows (); |
|
244 os << "# elements: " << elements << "\n"; |
|
245 for (int i = 0; i < elements; i++) |
|
246 { |
|
247 unsigned len = chm.cols (); |
|
248 os << "# length: " << len << "\n"; |
|
249 std::string tstr = chm.row_as_string (i, false, true); |
|
250 const char *tmp = tstr.data (); |
|
251 if (tstr.length () > len) |
|
252 panic_impossible (); |
|
253 os.write (X_CAST (char *, tmp), len); |
|
254 os << "\n"; |
|
255 } |
|
256 |
|
257 return true; |
|
258 } |
|
259 |
|
260 bool |
|
261 octave_char_matrix_str::load_ascii (std::istream& is) |
|
262 { |
|
263 int elements; |
|
264 bool success = true; |
|
265 std::streampos pos = is.tellg (); |
|
266 |
|
267 if (extract_keyword (is, "elements", elements, true)) |
|
268 { |
|
269 |
|
270 if (elements >= 0) |
|
271 { |
|
272 // XXX FIXME XXX -- need to be able to get max length |
|
273 // before doing anything. |
|
274 |
|
275 charMatrix chm (elements, 0); |
|
276 int max_len = 0; |
|
277 for (int i = 0; i < elements; i++) |
|
278 { |
|
279 int len; |
|
280 if (extract_keyword (is, "length", len) && len >= 0) |
|
281 { |
|
282 OCTAVE_LOCAL_BUFFER (char, tmp, len+1); |
|
283 |
|
284 if (len > 0 && ! is.read (X_CAST (char *, tmp), len)) |
|
285 { |
|
286 error ("load: failed to load string constant"); |
|
287 success = false; |
|
288 break; |
|
289 } |
|
290 else |
|
291 { |
|
292 tmp [len] = '\0'; |
|
293 if (len > max_len) |
|
294 { |
|
295 max_len = len; |
|
296 chm.resize (elements, max_len, 0); |
|
297 } |
|
298 chm.insert (tmp, i, 0); |
|
299 } |
|
300 } |
|
301 else |
|
302 { |
|
303 error ("load: failed to extract string length for element %d", |
|
304 i+1); |
|
305 success = false; |
|
306 } |
|
307 } |
|
308 |
|
309 if (! error_state) |
|
310 matrix = chm; |
|
311 |
|
312 } |
|
313 else |
|
314 { |
|
315 error ("load: failed to extract number of string elements"); |
|
316 success = false; |
|
317 } |
|
318 } |
|
319 else |
|
320 { |
|
321 // re-read the same line again |
|
322 is.clear (); |
|
323 is.seekg (pos); |
|
324 |
|
325 int len; |
|
326 |
|
327 if (extract_keyword (is, "length", len) && len >= 0) |
|
328 { |
|
329 // This is cruft for backward compatiability, but relatively harmless. |
|
330 |
|
331 OCTAVE_LOCAL_BUFFER (char, tmp, len+1); |
|
332 |
|
333 if (len > 0 && ! is.read (X_CAST (char *, tmp), len)) |
|
334 { |
|
335 error ("load: failed to load string constant"); |
|
336 } |
|
337 else |
|
338 { |
|
339 tmp [len] = '\0'; |
|
340 |
|
341 if (is) |
|
342 matrix = charMatrix (tmp); |
|
343 else |
|
344 error ("load: failed to load string constant"); |
|
345 } |
|
346 } |
|
347 } |
|
348 |
|
349 return success; |
|
350 } |
|
351 |
|
352 bool |
|
353 octave_char_matrix_str::save_binary (std::ostream& os, |
|
354 bool& /* save_as_floats */) |
|
355 { |
|
356 FOUR_BYTE_INT nr = rows (); |
|
357 os.write (X_CAST (char *, &nr), 4); |
|
358 charMatrix chm = char_matrix_value (); |
|
359 for (int i = 0; i < nr; i++) |
|
360 { |
|
361 FOUR_BYTE_INT len = chm.cols (); |
|
362 os.write (X_CAST (char *, &len), 4); |
|
363 std::string tstr = chm.row_as_string (i); |
|
364 const char *btmp = tstr.data (); |
|
365 os.write (X_CAST (char *, btmp), len); |
|
366 } |
|
367 return true; |
|
368 } |
|
369 |
|
370 bool |
|
371 octave_char_matrix_str::load_binary (std::istream& is, bool swap, |
|
372 oct_mach_info::float_format /* fmt */) |
|
373 { |
|
374 FOUR_BYTE_INT elements; |
|
375 if (! is.read (X_CAST (char *, &elements), 4)) |
|
376 return false; |
|
377 if (swap) |
|
378 swap_4_bytes (X_CAST (char *, &elements)); |
|
379 charMatrix chm (elements, 0); |
|
380 int max_len = 0; |
|
381 for (int i = 0; i < elements; i++) |
|
382 { |
|
383 FOUR_BYTE_INT len; |
|
384 if (! is.read (X_CAST (char *, &len), 4)) |
|
385 return false; |
|
386 if (swap) |
|
387 swap_4_bytes (X_CAST (char *, &len)); |
|
388 OCTAVE_LOCAL_BUFFER (char, btmp, len+1); |
|
389 if (! is.read (X_CAST (char *, btmp), len)) |
|
390 return false; |
|
391 if (len > max_len) |
|
392 { |
|
393 max_len = len; |
|
394 chm.resize (elements, max_len, 0); |
|
395 } |
|
396 btmp [len] = '\0'; |
|
397 chm.insert (btmp, i, 0); |
|
398 } |
|
399 |
|
400 matrix = chm; |
|
401 return true; |
|
402 } |
|
403 |
|
404 #if defined (HAVE_HDF5) |
|
405 bool |
|
406 octave_char_matrix_str::save_hdf5 (hid_t loc_id, const char *name, |
|
407 bool /* save_as_floats */) |
|
408 { |
|
409 hsize_t dimens[3]; |
|
410 hid_t space_hid = -1, type_hid = -1, data_hid = -1; |
|
411 bool retval = true; |
|
412 |
|
413 int nr = rows (); |
|
414 charMatrix chm = char_matrix_value (); |
|
415 int nc = chm.cols (); |
|
416 |
|
417 // create datatype for (null-terminated) string to write from: |
|
418 type_hid = H5Tcopy (H5T_C_S1); H5Tset_size (type_hid, nc + 1); |
|
419 if (type_hid < 0) return false; |
|
420 |
|
421 dimens[0] = nr; |
|
422 space_hid = H5Screate_simple (nr > 0 ? 1 : 0, dimens, (hsize_t*) 0); |
|
423 if (space_hid < 0) |
|
424 { |
|
425 H5Tclose (type_hid); |
|
426 return false; |
|
427 } |
|
428 |
|
429 data_hid = H5Dcreate (loc_id, name, type_hid, space_hid, H5P_DEFAULT); |
|
430 if (data_hid < 0) |
|
431 { |
|
432 H5Sclose (space_hid); |
|
433 H5Tclose (type_hid); |
|
434 return false; |
|
435 } |
|
436 |
|
437 OCTAVE_LOCAL_BUFFER (char, s, nr * (nc + 1)); |
|
438 |
|
439 for (int i = 0; i < nr; ++i) |
|
440 { |
|
441 std::string tstr = chm.row_as_string (i); |
|
442 strcpy (s + i * (nc+1), tstr.c_str ()); |
|
443 } |
|
444 |
|
445 retval = H5Dwrite (data_hid, type_hid, H5S_ALL, H5S_ALL, H5P_DEFAULT, |
|
446 (void*) s) >= 0; |
|
447 |
|
448 H5Dclose (data_hid); |
|
449 H5Tclose (type_hid); |
|
450 H5Sclose (space_hid); |
|
451 return retval; |
|
452 } |
|
453 |
|
454 bool |
|
455 octave_char_matrix_str::load_hdf5 (hid_t loc_id, const char *name, |
|
456 bool /* have_h5giterate_bug */) |
|
457 { |
|
458 hid_t data_hid = H5Dopen (loc_id, name); |
|
459 hid_t space_hid = H5Dget_space (data_hid); |
|
460 hsize_t rank = H5Sget_simple_extent_ndims (space_hid); |
|
461 hid_t type_hid = H5Dget_type (data_hid); |
|
462 |
|
463 if (rank == 0) |
|
464 { |
|
465 // a single string: |
|
466 int slen = H5Tget_size (type_hid); |
|
467 if (slen < 0) |
|
468 { |
|
469 H5Tclose (type_hid); |
|
470 H5Sclose (space_hid); |
|
471 H5Dclose (data_hid); |
|
472 return false; |
|
473 } |
|
474 else |
|
475 { |
|
476 OCTAVE_LOCAL_BUFFER (char, s, slen); |
|
477 // create datatype for (null-terminated) string |
|
478 // to read into: |
|
479 hid_t st_id = H5Tcopy (H5T_C_S1); |
|
480 H5Tset_size (st_id, slen); |
|
481 if (H5Dread (data_hid, st_id, H5S_ALL, H5S_ALL, |
|
482 H5P_DEFAULT, (void *) s) < 0) |
|
483 { |
|
484 H5Tclose (st_id); |
|
485 H5Tclose (type_hid); |
|
486 H5Sclose (space_hid); |
|
487 H5Dclose (data_hid); |
|
488 return false; |
|
489 } |
|
490 |
|
491 matrix = charMatrix (s); |
|
492 |
|
493 H5Tclose (st_id); |
|
494 H5Tclose (type_hid); |
|
495 H5Sclose (space_hid); |
|
496 H5Dclose (data_hid); |
|
497 return true; |
|
498 } |
|
499 } |
|
500 else if (rank == 1) |
|
501 { |
|
502 // string vector |
|
503 hsize_t elements, maxdim; |
|
504 H5Sget_simple_extent_dims (space_hid, &elements, &maxdim); |
|
505 int slen = H5Tget_size (type_hid); |
|
506 if (slen < 0) |
|
507 { |
|
508 H5Tclose (type_hid); |
|
509 H5Sclose (space_hid); |
|
510 H5Dclose (data_hid); |
|
511 return false; |
|
512 } |
|
513 else |
|
514 { |
|
515 // hdf5 string arrays store strings of all the |
|
516 // same physical length (I think), which is |
|
517 // slightly wasteful, but oh well. |
|
518 |
|
519 OCTAVE_LOCAL_BUFFER (char, s, elements * slen); |
|
520 |
|
521 // create datatype for (null-terminated) string |
|
522 // to read into: |
|
523 hid_t st_id = H5Tcopy (H5T_C_S1); |
|
524 H5Tset_size (st_id, slen); |
|
525 |
|
526 if (H5Dread (data_hid, st_id, H5S_ALL, H5S_ALL, |
|
527 H5P_DEFAULT, (void *) s) < 0) |
|
528 { |
|
529 H5Tclose (st_id); |
|
530 H5Tclose (type_hid); |
|
531 H5Sclose (space_hid); |
|
532 H5Dclose (data_hid); |
|
533 return false; |
|
534 } |
|
535 |
|
536 charMatrix chm (elements, slen - 1); |
|
537 for (hsize_t i = 0; i < elements; ++i) |
|
538 { |
|
539 chm.insert (s + i*slen, i, 0); |
|
540 } |
|
541 |
|
542 matrix = chm; |
|
543 |
|
544 H5Tclose (st_id); |
|
545 H5Tclose (type_hid); |
|
546 H5Sclose (space_hid); |
|
547 H5Dclose (data_hid); |
|
548 return true; |
|
549 } |
|
550 } |
|
551 else |
|
552 { |
|
553 H5Tclose (type_hid); |
|
554 H5Sclose (space_hid); |
|
555 H5Dclose (data_hid); |
|
556 return false; |
|
557 } |
|
558 } |
|
559 #endif |
|
560 |
2376
|
561 /* |
|
562 ;;; Local Variables: *** |
|
563 ;;; mode: C++ *** |
|
564 ;;; End: *** |
|
565 */ |