Mercurial > octave-nkf
annotate src/ov-range.cc @ 11944:278afaecddd4 release-3-0-x
fix leaving stray '\r' in stream when reading from CRLF data file
* * *
fix CRLF issues with text-mode reading in windows when loading ascii data
author | Benjamin Lindner <lindnerb@users.sourceforge.net> |
---|---|
date | Wed, 18 Mar 2009 15:23:14 +0100 |
parents | a1dbe9d80eee |
children |
rev | line source |
---|---|
2376 | 1 /* |
2 | |
7017 | 3 Copyright (C) 1996, 1997, 1998, 2000, 2002, 2003, 2004, 2005, 2006, |
4 2007 John W. Eaton | |
2376 | 5 |
6 This file is part of Octave. | |
7 | |
8 Octave is free software; you can redistribute it and/or modify it | |
9 under the terms of the GNU General Public License as published by the | |
7016 | 10 Free Software Foundation; either version 3 of the License, or (at your |
11 option) any later version. | |
2376 | 12 |
13 Octave is distributed in the hope that it will be useful, but WITHOUT | |
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 for more details. | |
17 | |
18 You should have received a copy of the GNU General Public License | |
7016 | 19 along with Octave; see the file COPYING. If not, see |
20 <http://www.gnu.org/licenses/>. | |
2376 | 21 |
22 */ | |
23 | |
24 #ifdef HAVE_CONFIG_H | |
25 #include <config.h> | |
26 #endif | |
27 | |
3503 | 28 #include <iostream> |
2901 | 29 |
2376 | 30 #include "lo-ieee.h" |
31 #include "lo-utils.h" | |
32 | |
33 #include "gripes.h" | |
34 #include "ops.h" | |
3933 | 35 #include "oct-obj.h" |
2376 | 36 #include "ov-range.h" |
37 #include "ov-re-mat.h" | |
2410 | 38 #include "ov-scalar.h" |
2376 | 39 #include "pr-output.h" |
40 | |
4687 | 41 #include "byte-swap.h" |
42 #include "ls-hdf5.h" | |
43 #include "ls-utils.h" | |
11944
278afaecddd4
fix leaving stray '\r' in stream when reading from CRLF data file
Benjamin Lindner <lindnerb@users.sourceforge.net>
parents:
7017
diff
changeset
|
44 #include "ls-ascii-helper.h" |
4687 | 45 |
3219 | 46 DEFINE_OCTAVE_ALLOCATOR (octave_range); |
2376 | 47 |
4612 | 48 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_range, "range", "double"); |
2376 | 49 |
5759 | 50 static octave_base_value * |
51 default_numeric_conversion_function (const octave_base_value& a) | |
2376 | 52 { |
53 CAST_CONV_ARG (const octave_range&); | |
54 | |
55 return new octave_matrix (v.matrix_value ()); | |
56 } | |
57 | |
5759 | 58 octave_base_value::type_conv_fcn |
2376 | 59 octave_range::numeric_conversion_function (void) const |
60 { | |
61 return default_numeric_conversion_function; | |
62 } | |
63 | |
5759 | 64 octave_base_value * |
2410 | 65 octave_range::try_narrowing_conversion (void) |
66 { | |
5759 | 67 octave_base_value *retval = 0; |
2410 | 68 |
69 switch (range.nelem ()) | |
70 { | |
71 case 1: | |
72 retval = new octave_scalar (range.base ()); | |
73 break; | |
74 | |
75 case 0: | |
4417 | 76 retval = new octave_matrix (Matrix (1, 0)); |
2410 | 77 break; |
78 | |
79 default: | |
80 break; | |
81 } | |
82 | |
83 return retval; | |
84 } | |
85 | |
2436 | 86 octave_value |
4247 | 87 octave_range::subsref (const std::string& type, |
4219 | 88 const std::list<octave_value_list>& idx) |
3933 | 89 { |
90 octave_value retval; | |
91 | |
92 switch (type[0]) | |
93 { | |
94 case '(': | |
95 retval = do_index_op (idx.front ()); | |
96 break; | |
97 | |
98 case '{': | |
99 case '.': | |
100 { | |
101 std::string nm = type_name (); | |
102 error ("%s cannot be indexed with %c", nm.c_str (), type[0]); | |
103 } | |
104 break; | |
105 | |
106 default: | |
107 panic_impossible (); | |
108 } | |
109 | |
110 return retval.next_subsref (type, idx); | |
111 } | |
112 | |
113 octave_value | |
5885 | 114 octave_range::do_index_op (const octave_value_list& idx, bool resize_ok) |
2436 | 115 { |
5775 | 116 // FIXME -- this doesn't solve the problem of |
2436 | 117 // |
118 // a = 1:5; a(1, 1, 1) | |
119 // | |
120 // and similar constructions. Hmm... | |
121 | |
5775 | 122 // FIXME -- using this constructor avoids possibly narrowing |
2436 | 123 // the range to a scalar value. Need a better solution to this |
124 // problem. | |
125 | |
126 octave_value tmp (new octave_matrix (range.matrix_value ())); | |
127 | |
3933 | 128 return tmp.do_index_op (idx, resize_ok); |
2436 | 129 } |
130 | |
2376 | 131 double |
132 octave_range::double_value (bool) const | |
133 { | |
4102 | 134 double retval = lo_ieee_nan_value (); |
2376 | 135 |
5275 | 136 octave_idx_type nel = range.nelem (); |
2376 | 137 |
4455 | 138 if (nel > 0) |
139 { | |
5781 | 140 gripe_implicit_conversion ("Octave:array-as-scalar", |
141 "range", "real scalar"); | |
4455 | 142 |
143 retval = range.base (); | |
144 } | |
2376 | 145 else |
146 gripe_invalid_conversion ("range", "real scalar"); | |
147 | |
148 return retval; | |
149 } | |
150 | |
151 octave_value | |
4017 | 152 octave_range::all (int dim) const |
2376 | 153 { |
5775 | 154 // FIXME -- this is a potential waste of memory. |
2436 | 155 |
156 Matrix m = range.matrix_value (); | |
157 | |
4017 | 158 return m.all (dim); |
2376 | 159 } |
160 | |
161 octave_value | |
4017 | 162 octave_range::any (int dim) const |
2376 | 163 { |
5775 | 164 // FIXME -- this is a potential waste of memory. |
4017 | 165 |
166 Matrix m = range.matrix_value (); | |
167 | |
168 return m.any (dim); | |
2376 | 169 } |
170 | |
171 bool | |
172 octave_range::is_true (void) const | |
173 { | |
174 bool retval = false; | |
2436 | 175 |
4478 | 176 if (range.nelem () != 0) |
2436 | 177 { |
5775 | 178 // FIXME -- this is a potential waste of memory. |
2436 | 179 |
180 Matrix m ((range.matrix_value () . all ()) . all ()); | |
181 | |
182 retval = (m.rows () == 1 && m.columns () == 1 && m (0, 0) != 0.0); | |
183 } | |
184 | |
2376 | 185 return retval; |
186 } | |
187 | |
188 Complex | |
189 octave_range::complex_value (bool) const | |
190 { | |
4102 | 191 double tmp = lo_ieee_nan_value (); |
192 | |
193 Complex retval (tmp, tmp); | |
2376 | 194 |
5275 | 195 octave_idx_type nel = range.nelem (); |
2376 | 196 |
4455 | 197 if (nel > 0) |
198 { | |
5781 | 199 gripe_implicit_conversion ("Octave:array-as-scalar", |
200 "range", "complex scalar"); | |
4455 | 201 |
202 retval = range.base (); | |
203 } | |
2376 | 204 else |
205 gripe_invalid_conversion ("range", "complex scalar"); | |
206 | |
207 return retval; | |
208 } | |
209 | |
5731 | 210 octave_value |
211 octave_range::resize (const dim_vector& dv, bool fill) const | |
212 { | |
213 NDArray retval = array_value (); | |
214 if (fill) | |
215 retval.resize (dv, NDArray::resize_fill_value()); | |
216 else | |
217 retval.resize (dv); | |
218 return retval; | |
219 } | |
220 | |
2376 | 221 octave_value |
5279 | 222 octave_range::convert_to_str_internal (bool pad, bool force, char type) const |
2449 | 223 { |
224 octave_value tmp (range.matrix_value ()); | |
5279 | 225 return tmp.convert_to_str (pad, force, type); |
2449 | 226 } |
227 | |
2376 | 228 void |
3523 | 229 octave_range::print (std::ostream& os, bool pr_as_read_syntax) const |
2901 | 230 { |
231 print_raw (os, pr_as_read_syntax); | |
232 newline (os); | |
233 } | |
234 | |
235 void | |
3523 | 236 octave_range::print_raw (std::ostream& os, bool pr_as_read_syntax) const |
2901 | 237 { |
238 octave_print_internal (os, range, pr_as_read_syntax, | |
239 current_print_indent_level ()); | |
240 } | |
241 | |
242 bool | |
3523 | 243 octave_range::print_name_tag (std::ostream& os, const std::string& name) const |
2376 | 244 { |
2901 | 245 bool retval = false; |
246 | |
5275 | 247 octave_idx_type n = range.nelem (); |
2901 | 248 |
249 indent (os); | |
250 | |
251 if (n == 0 || n == 1) | |
252 os << name << " = "; | |
253 else | |
254 { | |
255 os << name << " ="; | |
256 newline (os); | |
257 newline (os); | |
258 retval = true; | |
259 } | |
260 | |
261 return retval; | |
2376 | 262 } |
263 | |
4687 | 264 // Skip white space and comments on stream IS. |
265 | |
266 static void | |
267 skip_comments (std::istream& is) | |
268 { | |
269 char c = '\0'; | |
270 while (is.get (c)) | |
271 { | |
272 if (c == ' ' || c == '\t' || c == '\n') | |
273 ; // Skip whitespace on way to beginning of next line. | |
274 else | |
275 break; | |
276 } | |
277 | |
11944
278afaecddd4
fix leaving stray '\r' in stream when reading from CRLF data file
Benjamin Lindner <lindnerb@users.sourceforge.net>
parents:
7017
diff
changeset
|
278 // Skip to beginning of next line, ignoring everything. |
278afaecddd4
fix leaving stray '\r' in stream when reading from CRLF data file
Benjamin Lindner <lindnerb@users.sourceforge.net>
parents:
7017
diff
changeset
|
279 skip_until_newline (is, false); |
278afaecddd4
fix leaving stray '\r' in stream when reading from CRLF data file
Benjamin Lindner <lindnerb@users.sourceforge.net>
parents:
7017
diff
changeset
|
280 |
4687 | 281 } |
282 | |
283 bool | |
6974 | 284 octave_range::save_ascii (std::ostream& os) |
4687 | 285 { |
286 Range r = range_value (); | |
287 double base = r.base (); | |
288 double limit = r.limit (); | |
289 double inc = r.inc (); | |
290 | |
291 os << "# base, limit, increment\n"; | |
292 octave_write_double (os, base); | |
293 os << " "; | |
294 octave_write_double (os, limit); | |
295 os << " "; | |
296 octave_write_double (os, inc); | |
297 os << "\n"; | |
298 | |
299 return true; | |
300 } | |
301 | |
302 bool | |
303 octave_range::load_ascii (std::istream& is) | |
304 { | |
305 // # base, limit, range comment added by save (). | |
306 skip_comments (is); | |
307 | |
308 is >> range; | |
309 | |
310 if (!is) | |
311 { | |
312 error ("load: failed to load range constant"); | |
313 return false; | |
314 } | |
315 | |
316 return true; | |
317 } | |
318 | |
319 bool | |
320 octave_range::save_binary (std::ostream& os, bool& /* save_as_floats */) | |
321 { | |
5760 | 322 char tmp = LS_DOUBLE; |
323 os.write (reinterpret_cast<char *> (&tmp), 1); | |
4687 | 324 Range r = range_value (); |
325 double bas = r.base (); | |
326 double lim = r.limit (); | |
327 double inc = r.inc (); | |
5760 | 328 os.write (reinterpret_cast<char *> (&bas), 8); |
329 os.write (reinterpret_cast<char *> (&lim), 8); | |
330 os.write (reinterpret_cast<char *> (&inc), 8); | |
4687 | 331 |
332 return true; | |
333 } | |
334 | |
335 bool | |
336 octave_range::load_binary (std::istream& is, bool swap, | |
337 oct_mach_info::float_format /* fmt */) | |
338 { | |
339 char tmp; | |
5760 | 340 if (! is.read (reinterpret_cast<char *> (&tmp), 1)) |
4687 | 341 return false; |
342 double bas, lim, inc; | |
5760 | 343 if (! is.read (reinterpret_cast<char *> (&bas), 8)) |
4687 | 344 return false; |
345 if (swap) | |
4944 | 346 swap_bytes<8> (&bas); |
5760 | 347 if (! is.read (reinterpret_cast<char *> (&lim), 8)) |
4687 | 348 return false; |
349 if (swap) | |
4944 | 350 swap_bytes<8> (&lim); |
5760 | 351 if (! is.read (reinterpret_cast<char *> (&inc), 8)) |
4687 | 352 return false; |
353 if (swap) | |
4944 | 354 swap_bytes<8> (&inc); |
4687 | 355 Range r (bas, lim, inc); |
356 range = r; | |
357 return true; | |
358 } | |
359 | |
360 #if defined (HAVE_HDF5) | |
4944 | 361 |
4687 | 362 // The following subroutines creates an HDF5 representation of the way |
363 // we will store Octave range types (triplets of floating-point numbers). | |
364 // NUM_TYPE is the HDF5 numeric type to use for storage (e.g. | |
365 // H5T_NATIVE_DOUBLE to save as 'double'). Note that any necessary | |
366 // conversions are handled automatically by HDF5. | |
367 | |
368 static hid_t | |
369 hdf5_make_range_type (hid_t num_type) | |
370 { | |
371 hid_t type_id = H5Tcreate (H5T_COMPOUND, sizeof (double) * 3); | |
372 | |
373 H5Tinsert (type_id, "base", 0 * sizeof (double), num_type); | |
374 H5Tinsert (type_id, "limit", 1 * sizeof (double), num_type); | |
375 H5Tinsert (type_id, "increment", 2 * sizeof (double), num_type); | |
376 | |
377 return type_id; | |
378 } | |
379 | |
380 bool | |
381 octave_range::save_hdf5 (hid_t loc_id, const char *name, | |
382 bool /* save_as_floats */) | |
383 { | |
4792 | 384 hsize_t dimens[3]; |
4687 | 385 hid_t space_hid = -1, type_hid = -1, data_hid = -1; |
386 bool retval = true; | |
387 | |
4815 | 388 space_hid = H5Screate_simple (0, dimens, 0); |
4687 | 389 if (space_hid < 0) return false; |
390 | |
391 type_hid = hdf5_make_range_type (H5T_NATIVE_DOUBLE); | |
392 if (type_hid < 0) | |
393 { | |
394 H5Sclose (space_hid); | |
395 return false; | |
396 } | |
397 | |
398 data_hid = H5Dcreate (loc_id, name, type_hid, space_hid, H5P_DEFAULT); | |
399 if (data_hid < 0) | |
400 { | |
401 H5Sclose (space_hid); | |
402 H5Tclose (type_hid); | |
403 return false; | |
404 } | |
405 | |
406 Range r = range_value (); | |
407 double range_vals[3]; | |
408 range_vals[0] = r.base (); | |
409 range_vals[1] = r.limit (); | |
410 range_vals[2] = r.inc (); | |
411 | |
412 retval = H5Dwrite (data_hid, type_hid, H5S_ALL, H5S_ALL, H5P_DEFAULT, | |
4815 | 413 range_vals) >= 0; |
4687 | 414 |
415 H5Dclose (data_hid); | |
416 H5Tclose (type_hid); | |
417 H5Sclose (space_hid); | |
4837 | 418 |
4687 | 419 return retval; |
420 } | |
421 | |
422 bool | |
423 octave_range::load_hdf5 (hid_t loc_id, const char *name, | |
424 bool /* have_h5giterate_bug */) | |
425 { | |
426 bool retval = false; | |
4837 | 427 |
4687 | 428 hid_t data_hid = H5Dopen (loc_id, name); |
429 hid_t type_hid = H5Dget_type (data_hid); | |
430 | |
431 hid_t range_type = hdf5_make_range_type (H5T_NATIVE_DOUBLE); | |
432 | |
433 if (! hdf5_types_compatible (type_hid, range_type)) | |
434 { | |
4837 | 435 H5Tclose (range_type); |
4687 | 436 H5Dclose (data_hid); |
437 return false; | |
438 } | |
439 | |
440 hid_t space_hid = H5Dget_space (data_hid); | |
441 hsize_t rank = H5Sget_simple_extent_ndims (space_hid); | |
442 | |
443 if (rank != 0) | |
444 { | |
4837 | 445 H5Tclose (range_type); |
4687 | 446 H5Sclose (space_hid); |
447 H5Dclose (data_hid); | |
448 return false; | |
449 } | |
450 | |
451 double rangevals[3]; | |
452 if (H5Dread (data_hid, range_type, H5S_ALL, H5S_ALL, H5P_DEFAULT, | |
4815 | 453 rangevals) >= 0) |
4687 | 454 { |
455 retval = true; | |
456 Range r (rangevals[0], rangevals[1], rangevals[2]); | |
457 range = r; | |
458 } | |
459 | |
4837 | 460 H5Tclose (range_type); |
4687 | 461 H5Sclose (space_hid); |
462 H5Dclose (data_hid); | |
4837 | 463 |
4687 | 464 return retval; |
465 } | |
4944 | 466 |
4687 | 467 #endif |
468 | |
5900 | 469 mxArray * |
470 octave_range::as_mxArray (void) const | |
471 { | |
472 mxArray *retval = new mxArray (mxDOUBLE_CLASS, dims (), mxREAL); | |
473 | |
474 double *pr = static_cast<double *> (retval->get_data ()); | |
475 | |
6686 | 476 mwSize nel = numel (); |
5900 | 477 |
478 Matrix m = matrix_value (); | |
479 | |
480 const double *p = m.data (); | |
481 | |
6686 | 482 for (mwSize i = 0; i < nel; i++) |
5900 | 483 pr[i] = p[i]; |
484 | |
485 return retval; | |
486 } | |
487 | |
2376 | 488 /* |
489 ;;; Local Variables: *** | |
490 ;;; mode: C++ *** | |
491 ;;; End: *** | |
492 */ |