GNU Octave 11.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 
Loading...
Searching...
No Matches
data-conv.cc
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 1996-2026 The Octave Project Developers
4//
5// See the file COPYRIGHT.md in the top-level directory of this
6// distribution or <https://octave.org/copyright/>.
7//
8// This file is part of Octave.
9//
10// Octave is free software: you can redistribute it and/or modify it
11// under the terms of the GNU General Public License as published by
12// the Free Software Foundation, either version 3 of the License, or
13// (at your option) any later version.
14//
15// Octave is distributed in the hope that it will be useful, but
16// WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU General Public License for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with Octave; see the file COPYING. If not, see
22// <https://www.gnu.org/licenses/>.
23//
24////////////////////////////////////////////////////////////////////////
25
26#if defined (HAVE_CONFIG_H)
27# include "config.h"
28#endif
29
30#include <cctype>
31#include <cstdlib>
32
33#include <istream>
34#include <limits>
35#include <ostream>
36#include <vector>
37
38#include "byte-swap.h"
39#include "data-conv.h"
40#include "lo-ieee.h"
41#include "oct-error.h"
42#include "oct-locbuf.h"
43
44// FIXME: Almost all platform-dependent sizes such as "short" are now defined
45// to take fixed values (such as 2B). This was instigated for Matlab
46// compatibility (bug #41672). It means a lot of this code is probably
47// obsolete and could be pared down or removed entirely.
48
49#if defined (OCTAVE_HAVE_LONG_LONG_INT)
50# define FIND_SIZED_INT_TYPE(VAL, BITS, TQ, Q) \
51 do \
52 { \
53 int sz = BITS / std::numeric_limits<unsigned char>::digits; \
54 if (sizeof (TQ char) == sz) \
55 VAL = oct_data_conv::dt_ ## Q ## char; \
56 else if (sizeof (TQ short) == sz) \
57 VAL = oct_data_conv::dt_ ## Q ## short; \
58 else if (sizeof (TQ int) == sz) \
59 VAL = oct_data_conv::dt_ ## Q ## int; \
60 else if (sizeof (TQ long) == sz) \
61 VAL = oct_data_conv::dt_ ## Q ## long; \
62 else if (sizeof (TQ long long) == sz) \
63 VAL = oct_data_conv::dt_ ## Q ## longlong; \
64 else \
65 VAL = oct_data_conv::dt_unknown; \
66 } \
67 while (0)
68#else
69# define FIND_SIZED_INT_TYPE(VAL, BITS, TQ, Q) \
70 do \
71 { \
72 int sz = BITS / std::numeric_limits<unsigned char>::digits; \
73 if (sizeof (TQ char) == sz) \
74 VAL = oct_data_conv::dt_ ## Q ## char; \
75 else if (sizeof (TQ short) == sz) \
76 VAL = oct_data_conv::dt_ ## Q ## short; \
77 else if (sizeof (TQ int) == sz) \
78 VAL = oct_data_conv::dt_ ## Q ## int; \
79 else if (sizeof (TQ long) == sz) \
80 VAL = oct_data_conv::dt_ ## Q ## long; \
81 else \
82 VAL = oct_data_conv::dt_unknown; \
83 } \
84 while (0)
85#endif
86
87#define FIND_SIZED_FLOAT_TYPE(VAL, BITS) \
88 do \
89 { \
90 int sz = BITS / std::numeric_limits<unsigned char>::digits; \
91 if (sizeof (float) == sz) \
92 VAL = oct_data_conv::dt_float; \
93 else if (sizeof (double) == sz) \
94 VAL = oct_data_conv::dt_double; \
95 else \
96 VAL = oct_data_conv::dt_unknown; \
97 } \
98 while (0)
99
100// I'm not sure it is worth the trouble, but let's use a lookup table
101// for the types that are supposed to be a specific number of bits
102// wide. Given the macros above, this should work as long as
103// std::numeric_limits<unsigned char>::digits is a multiple of 8 and
104// there are types with the right sizes.
105//
106// The sized data type lookup table has the following format:
107//
108// bits
109// +----+----+----+----+
110// | 8 | 16 | 32 | 64 |
111// +----+----+----+----+
112// signed integer | | | | |
113// +----+----+----+----+
114// unsigned integer | | | | |
115// +----+----+----+----+
116// floating point | | | | |
117// +----+----+----+----+
118//
119// So, the 0,3 element is supposed to contain the oct_data_conv enum
120// value corresponding to the correct native data type for a signed
121// 32-bit integer.
122
123static void
124init_sized_type_lookup_table (oct_data_conv::data_type table[3][4])
125{
126 int bits = 8;
127
128 for (int i = 0; i < 4; i++)
129 {
130 FIND_SIZED_INT_TYPE (table[0][i], bits, , );
131
132 FIND_SIZED_INT_TYPE (table[1][i], bits, unsigned, u);
133
134 FIND_SIZED_FLOAT_TYPE (table[2][i], bits);
135
136 bits *= 2;
137 }
138}
139
140static std::string
141strip_spaces (const std::string& str)
142{
143 std::size_t n = str.length ();
144
145 std::size_t k = 0;
146
147 std::string s (n, '\0');
148
149 for (std::size_t i = 0; i < n; i++)
150 if (! isspace (str[i]))
151 s[k++] = tolower (str[i]);
152
153 s.resize (k);
154
155 return s;
156}
157
158#define GET_SIZED_INT_TYPE(T, U) \
159 do \
160 { \
161 switch (sizeof (T)) \
162 { \
163 case 1: \
164 retval = dt_ ## U ## int8; \
165 break; \
166 \
167 case 2: \
168 retval = dt_ ## U ## int16; \
169 break; \
170 \
171 case 4: \
172 retval = dt_ ## U ## int32; \
173 break; \
174 \
175 case 8: \
176 retval = dt_ ## U ## int64; \
177 break; \
178 \
179 default: \
180 retval = dt_unknown; \
181 break; \
182 } \
183 } \
184 while (0)
185
186std::size_t
188{
189 std::size_t retval = -1;
190
191 switch (dt)
192 {
194 retval = sizeof (int8_t);
195 break;
196
198 retval = sizeof (uint8_t);
199 break;
200
202 retval = sizeof (int16_t);
203 break;
204
206 retval = sizeof (uint16_t);
207 break;
208
210 retval = sizeof (int32_t);
211 break;
212
214 retval = sizeof (uint32_t);
215 break;
216
218 retval = sizeof (int64_t);
219 break;
220
222 retval = sizeof (uint64_t);
223 break;
224
227 retval = sizeof (float);
228 break;
229
231 retval = sizeof (double);
232 break;
233
235 retval = sizeof (char);
236 break;
237
239 retval = sizeof (signed char);
240 break;
241
243 retval = sizeof (unsigned char);
244 break;
245
247 retval = sizeof (short);
248 break;
249
251 retval = sizeof (unsigned short);
252 break;
253
255 retval = sizeof (int);
256 break;
257
259 retval = sizeof (unsigned int);
260 break;
261
263 retval = sizeof (long);
264 break;
265
267 retval = sizeof (unsigned long);
268 break;
269
271 retval = sizeof (long long);
272 break;
273
275 retval = sizeof (unsigned long long);
276 break;
277
279 retval = sizeof (bool);
280 break;
281
283 default:
284 (*current_liboctave_error_handler)
285 ("oct_data_conv::data_type_size: unknown data type");
286 break;
287 }
288
289 return retval;
290}
291
294{
295 data_type retval = dt_unknown;
296
297 static bool initialized = false;
298
299 static data_type sized_type_table[3][4];
300
301 if (! initialized)
302 {
303 init_sized_type_lookup_table (sized_type_table);
304
305 initialized = true;
306 }
307
308 std::string s = strip_spaces (str);
309
310 // Organized so most frequent precision appears first
311 if (s == "uint8")
312 retval = dt_uint8;
313 else if (s == "double" || s == "float64" || s == "real*8")
314 retval = dt_double;
315 else if (s == "single" || s == "float" || s == "float32" || s == "real*4")
316 retval = dt_single;
317 else if (s == "char" || s == "char*1")
318 retval = dt_char;
319 else if (s == "int")
320 retval = dt_int32;
321 else if (s == "uchar" || s == "unsignedchar")
322 retval = dt_uint8;
323 else if (s == "schar" || s == "signedchar")
324 retval = dt_int8;
325 else if (s == "int8" || s == "integer*1")
326 retval = dt_int8;
327 else if (s == "int16" || s == "integer*2")
328 retval = dt_int16;
329 else if (s == "uint16")
330 retval = dt_uint16;
331 else if (s == "int32" || s == "integer*4")
332 retval = dt_int32;
333 else if (s == "uint32")
334 retval = dt_uint32;
335 else if (s == "int64" || s == "integer*8")
336 retval = dt_int64;
337 else if (s == "uint64")
338 retval = dt_uint64;
339 else if (s == "short")
340 retval = dt_int16;
341 else if (s == "ushort" || s == "unsignedshort")
342 retval = dt_uint16;
343 else if (s == "uint" || s == "unsignedint")
344 retval = dt_uint32;
345 else if (s == "long")
346 retval = dt_int32;
347 else if (s == "ulong" || s == "unsignedlong")
348 retval = dt_uint32;
349 // FIXME: The following are undocumented precisions
350 else if (s == "longlong")
351 GET_SIZED_INT_TYPE (long long, );
352 else if (s == "ulonglong" || s == "unsignedlonglong")
353 GET_SIZED_INT_TYPE (unsigned long long, u);
354 else if (s == "logical")
355 retval = dt_logical;
356 else
357 (*current_liboctave_error_handler) ("invalid data type specified");
358
359 if (retval == dt_unknown)
360 (*current_liboctave_error_handler)
361 ("unable to find matching native data type for %s", s.c_str ());
362
363 return retval;
364}
365
366void
367oct_data_conv::string_to_data_type (const std::string& str, int& block_size,
368 oct_data_conv::data_type& input_type,
369 oct_data_conv::data_type& output_type)
370{
371 block_size = 1;
372 input_type = dt_uchar;
373 output_type = dt_double;
374
375 bool input_is_output = false;
376
377 std::string s = strip_spaces (str);
378
379 std::size_t pos = 0;
380
381 if (s[0] == '*')
382 input_is_output = true;
383 else
384 {
385 std::size_t len = s.length ();
386
387 while (pos < len && isdigit (s[pos]))
388 pos++;
389
390 if (pos > 0)
391 {
392 if (s[pos] == '*')
393 {
394 try
395 {
396 block_size = std::stoi (s);
397 s = s.substr (pos+1);
398 }
399 catch (const std::invalid_argument&)
400 {
401 (*current_liboctave_error_handler)
402 ("invalid repeat count in '%s'", s.c_str ());
403 }
404 catch (const std::out_of_range&)
405 {
406 (*current_liboctave_error_handler)
407 ("repeat count out of range in '%s'", s.c_str ());
408 }
409 }
410 else
412 ("invalid repeat count in '%s'", str.c_str ());
413 }
414 }
415
416 pos = s.find ('=');
417
418 if (pos != std::string::npos)
419 {
420 if (s[pos+1] == '>')
421 {
422 std::string s1;
423
424 if (input_is_output)
425 {
426 s1 = s.substr (1, pos-1);
427
428 (*current_liboctave_warning_with_id_handler)
429 ("Octave:fread-precision-syntax",
430 "warning: ignoring leading * in fread precision");
431 }
432 else
433 s1 = s.substr (0, pos);
434
435 input_type = string_to_data_type (s1);
436 output_type = string_to_data_type (s.substr (pos+2));
437 }
438 else
440 ("fread: invalid precision specified");
441 }
442 else
443 {
444 if (input_is_output)
445 s = s.substr (1);
446
447 input_type = string_to_data_type (s);
448
449 if (input_is_output)
450 output_type = input_type;
451 }
452}
453
454void
455oct_data_conv::string_to_data_type (const std::string& str, int& block_size,
456 oct_data_conv::data_type& output_type)
457{
458 block_size = 1;
459 output_type = dt_double;
460
461 std::string s = strip_spaces (str);
462
463 std::size_t pos = 0;
464
465 std::size_t len = s.length ();
466
467 while (pos < len && isdigit (s[pos]))
468 pos++;
469
470 if (pos > 0)
471 {
472 if (s[pos] == '*')
473 {
474 try
475 {
476 block_size = std::stoi (s);
477 s = s.substr (pos+1);
478 }
479 catch (const std::invalid_argument&)
480 {
481 (*current_liboctave_error_handler)
482 ("invalid repeat count in '%s'", s.c_str ());
483 }
484 catch (const std::out_of_range&)
485 {
486 (*current_liboctave_error_handler)
487 ("repeat count out of range in '%s'", s.c_str ());
488 }
489 }
490 else
492 ("invalid repeat count in '%s'", str.c_str ());
493 }
494
495 output_type = string_to_data_type (s);
496}
497
498std::string
500{
501 std::string retval;
502
503 switch (dt)
504 {
506 retval = "int8";
507 break;
508
510 retval = "uint8";
511 break;
512
514 retval = "int16";
515 break;
516
518 retval = "uint16";
519 break;
520
522 retval = "int32";
523 break;
524
526 retval = "uint32";
527 break;
528
530 retval = "int64";
531 break;
532
534 retval = "uint64";
535 break;
536
538 retval = "single";
539 break;
540
542 retval = "double";
543 break;
544
546 retval = "char";
547 break;
548
550 retval = "signed char";
551 break;
552
554 retval = "unsigned char";
555 break;
556
558 retval = "short";
559 break;
560
562 retval = "unsigned short";
563 break;
564
566 retval = "int";
567 break;
568
570 retval = "unsigned int";
571 break;
572
574 retval = "long";
575 break;
576
578 retval = "unsigned long";
579 break;
580
582 retval = "long long";
583 break;
584
586 retval = "unsigned long long";
587 break;
588
590 retval = "float";
591 break;
592
594 retval = "logical";
595 break;
596
598 default:
599 retval = "unknown";
600 break;
601 }
602
603 return retval;
604}
605
606#define LS_DO_READ(TYPE, swap, data, size, len, stream) \
607 do \
608 { \
609 if (len > 0) \
610 { \
611 OCTAVE_LOCAL_BUFFER (TYPE, ptr, len); \
612 std::streamsize n_bytes = size * static_cast<std::streamsize> (len); \
613 do_read (stream, reinterpret_cast<char *> (ptr), n_bytes); \
614 if (! stream) \
615 return; \
616 if (swap) \
617 swap_bytes< size > (ptr, len); \
618 for (octave_idx_type i = 0; i < len; i++) \
619 data[i] = ptr[i]; \
620 } \
621 } \
622 while (0)
623
624// Have to use copy here to avoid writing over data accessed via
625// Matrix::data ().
626
627#define LS_DO_WRITE(TYPE, data, size, len, stream) \
628 do \
629 { \
630 char tmp_type = type; \
631 stream.write (&tmp_type, 1); \
632 if (len > 0) \
633 { \
634 OCTAVE_LOCAL_BUFFER (TYPE, ptr, len); \
635 for (octave_idx_type i = 0; i < len; i++) \
636 ptr[i] = static_cast<TYPE> (data[i]); \
637 std::streamsize n_bytes = size * static_cast<std::streamsize> (len); \
638 do_write (stream, reinterpret_cast<const char *> (ptr), n_bytes); \
639 } \
640 } \
641 while (0)
642
643// Loading variables from files.
644
645OCTAVE_NORETURN static
646void
647err_unrecognized_float_fmt ()
648{
649 (*current_liboctave_error_handler)
650 ("unrecognized floating point format requested");
651}
652
653// But first, some data conversion routines.
654
655// Currently, we only handle conversions for the IEEE types. To fix
656// that, make more of the following routines work.
657
658// FIXME: assumes sizeof (Complex) == 8
659// FIXME: assumes sizeof (double) == 8
660// FIXME: assumes sizeof (float) == 4
661
662static void
663IEEE_big_double_to_IEEE_little_double (void *d, octave_idx_type len)
664{
666}
667
668static void
669IEEE_big_float_to_IEEE_little_float (void *d, octave_idx_type len)
670{
672}
673
674static void
675IEEE_little_double_to_IEEE_big_double (void *d, octave_idx_type len)
676{
678}
679
680static void
681IEEE_little_float_to_IEEE_big_float (void *d, octave_idx_type len)
682{
684}
685
686void
688 octave::mach_info::float_format from_fmt,
689 octave::mach_info::float_format to_fmt)
690{
691 switch (to_fmt)
692 {
693 case octave::mach_info::flt_fmt_ieee_little_endian:
694 switch (from_fmt)
695 {
696 case octave::mach_info::flt_fmt_ieee_little_endian:
697 break;
698
699 case octave::mach_info::flt_fmt_ieee_big_endian:
700 IEEE_big_double_to_IEEE_little_double (data, len);
701 break;
702
703 default:
704 err_unrecognized_float_fmt ();
705 break;
706 }
707 break;
708
709 case octave::mach_info::flt_fmt_ieee_big_endian:
710 switch (from_fmt)
711 {
712 case octave::mach_info::flt_fmt_ieee_little_endian:
713 IEEE_little_double_to_IEEE_big_double (data, len);
714 break;
715
716 case octave::mach_info::flt_fmt_ieee_big_endian:
717 break;
718
719 default:
720 err_unrecognized_float_fmt ();
721 break;
722 }
723 break;
724
725 default:
726 (*current_liboctave_error_handler)
727 ("impossible state reached in file '%s' at line %d",
728 __FILE__, __LINE__);
729 break;
730 }
731}
732
733void
735 octave::mach_info::float_format from_fmt,
736 octave::mach_info::float_format to_fmt)
737{
738 switch (to_fmt)
739 {
740 case octave::mach_info::flt_fmt_ieee_little_endian:
741 switch (from_fmt)
742 {
743 case octave::mach_info::flt_fmt_ieee_little_endian:
744 break;
745
746 case octave::mach_info::flt_fmt_ieee_big_endian:
747 IEEE_big_float_to_IEEE_little_float (data, len);
748 break;
749
750 default:
751 err_unrecognized_float_fmt ();
752 break;
753 }
754 break;
755
756 case octave::mach_info::flt_fmt_ieee_big_endian:
757 switch (from_fmt)
758 {
759 case octave::mach_info::flt_fmt_ieee_little_endian:
760 IEEE_little_float_to_IEEE_big_float (data, len);
761 break;
762
763 case octave::mach_info::flt_fmt_ieee_big_endian:
764 break;
765
766 default:
767 err_unrecognized_float_fmt ();
768 break;
769 }
770 break;
771
772 default:
773 (*current_liboctave_error_handler)
774 ("impossible state reached in file '%s' at line %d",
775 __FILE__, __LINE__);
776 break;
777 }
778}
779
780void
781do_float_format_conversion (void *data, std::size_t sz, octave_idx_type len,
782 octave::mach_info::float_format from_fmt,
783 octave::mach_info::float_format to_fmt)
784{
785 switch (sz)
786 {
787 case sizeof (float):
788 do_float_format_conversion (data, len, from_fmt, to_fmt);
789 break;
790
791 case sizeof (double):
792 do_double_format_conversion (data, len, from_fmt, to_fmt);
793 break;
794
795 default:
796 (*current_liboctave_error_handler)
797 ("impossible state reached in file '%s' at line %d",
798 __FILE__, __LINE__);
799 break;
800 }
801}
802
803static void
804do_read (std::istream& is, char *byte_data, std::streamsize n_bytes)
805{
806 // read large data in chunks of 64 MiB
807 constexpr std::streamsize chunk_size = 64 * 1024 * 1024;
808 for (std::streamsize offset = 0; offset < n_bytes; )
809 {
810 std::streamsize to_read = std::min (chunk_size, n_bytes - offset);
811 is.read (byte_data + offset, to_read);
812
813 if (! is)
814 return;
815
816 offset += to_read;
817 }
818}
819void
820read_doubles (std::istream& is, double *data, save_type type,
821 octave_idx_type len, bool swap,
822 octave::mach_info::float_format fmt)
823{
824 switch (type)
825 {
826 case LS_U_CHAR:
827 LS_DO_READ (uint8_t, swap, data, 1, len, is);
828 break;
829
830 case LS_U_SHORT:
831 LS_DO_READ (uint16_t, swap, data, 2, len, is);
832 break;
833
834 case LS_U_INT:
835 LS_DO_READ (uint32_t, swap, data, 4, len, is);
836 break;
837
838 case LS_CHAR:
839 LS_DO_READ (int8_t, swap, data, 1, len, is);
840 break;
841
842 case LS_SHORT:
843 LS_DO_READ (int16_t, swap, data, 2, len, is);
844 break;
845
846 case LS_INT:
847 LS_DO_READ (int32_t, swap, data, 4, len, is);
848 break;
849
850 case LS_FLOAT:
851 {
852 OCTAVE_LOCAL_BUFFER (float, ptr, len);
853 std::streamsize n_bytes = sizeof (float) * static_cast<std::streamsize> (len);
854 do_read (is, reinterpret_cast<char *> (ptr), n_bytes);
855 if (! is)
856 return;
858 for (octave_idx_type i = 0; i < len; i++)
859 data[i] = ptr[i];
860 }
861 break;
862
863 case LS_DOUBLE: // No conversion necessary.
864 {
865 std::streamsize n_bytes = sizeof (double) * static_cast<std::streamsize> (len);
866 do_read (is, reinterpret_cast<char *> (data), n_bytes);
867 if (! is)
868 return;
869 do_double_format_conversion (data, len, fmt);
870 // FIXME: Potentially add conversion code for MIPS NA here, Bug #59830.
871 //
872 // for (int i = 0; i < len; i++)
873 // data[i] = __lo_ieee_replace_MIPS_NA (data[i]);
874 }
875 break;
876
877 default:
878 is.clear (std::ios::failbit | is.rdstate ());
879 break;
880 }
881}
882
883void
884read_floats (std::istream& is, float *data, save_type type,
885 octave_idx_type len, bool swap,
886 octave::mach_info::float_format fmt)
887{
888 switch (type)
889 {
890 case LS_U_CHAR:
891 LS_DO_READ (uint8_t, swap, data, 1, len, is);
892 break;
893
894 case LS_U_SHORT:
895 LS_DO_READ (uint16_t, swap, data, 2, len, is);
896 break;
897
898 case LS_U_INT:
899 LS_DO_READ (uint32_t, swap, data, 4, len, is);
900 break;
901
902 case LS_CHAR:
903 LS_DO_READ (int8_t, swap, data, 1, len, is);
904 break;
905
906 case LS_SHORT:
907 LS_DO_READ (int16_t, swap, data, 2, len, is);
908 break;
909
910 case LS_INT:
911 LS_DO_READ (int32_t, swap, data, 4, len, is);
912 break;
913
914 case LS_FLOAT: // No conversion necessary.
915 {
916 std::streamsize n_bytes = sizeof (float) * static_cast<std::streamsize> (len);
917 do_read (is, reinterpret_cast<char *> (data), n_bytes);
918 if (! is)
919 return;
920 do_float_format_conversion (data, len, fmt);
921 }
922 break;
923
924 case LS_DOUBLE:
925 {
926 OCTAVE_LOCAL_BUFFER (double, ptr, len);
927 std::streamsize n_bytes = 8 * static_cast<std::streamsize> (len);
928 do_read (is, reinterpret_cast<char *> (ptr), n_bytes);
929 if (! is)
930 return;
932 for (octave_idx_type i = 0; i < len; i++)
933 data[i] = ptr[i];
934 }
935 break;
936
937 default:
938 is.clear (std::ios::failbit | is.rdstate ());
939 break;
940 }
941}
942
943static void
944do_write (std::ostream& os, const char *byte_data, std::streamsize n_bytes)
945{
946 // write large data in chunks of 64 MiB
947 constexpr std::streamsize chunk_size = 64 * 1024 * 1024;
948 for (std::streamsize written = 0; written < n_bytes; )
949 {
950 std::streamsize remaining = n_bytes - written;
951 std::streamsize to_write = std::min (chunk_size, remaining);
952 os.write (byte_data + written, to_write);
953 if (! os)
954 return;
955 written += to_write;
956 }
957}
958
959void
960write_doubles (std::ostream& os, const double *data, save_type type,
962{
963 switch (type)
964 {
965 case LS_U_CHAR:
966 LS_DO_WRITE (uint8_t, data, 1, len, os);
967 break;
968
969 case LS_U_SHORT:
970 LS_DO_WRITE (uint16_t, data, 2, len, os);
971 break;
972
973 case LS_U_INT:
974 LS_DO_WRITE (uint32_t, data, 4, len, os);
975 break;
976
977 case LS_CHAR:
978 LS_DO_WRITE (int8_t, data, 1, len, os);
979 break;
980
981 case LS_SHORT:
982 LS_DO_WRITE (int16_t, data, 2, len, os);
983 break;
984
985 case LS_INT:
986 LS_DO_WRITE (int32_t, data, 4, len, os);
987 break;
988
989 case LS_FLOAT:
990 LS_DO_WRITE (float, data, 4, len, os);
991 break;
992
993 case LS_DOUBLE: // No conversion necessary.
994 {
995 char tmp_type = static_cast<char> (type);
996 os.write (&tmp_type, 1);
997
998 std::streamsize n_bytes = sizeof (double) * static_cast<std::streamsize> (len);
999 do_write (os, reinterpret_cast<const char *> (data), n_bytes);
1000 }
1001 break;
1002
1003 default:
1004 (*current_liboctave_error_handler)
1005 ("unrecognized data format requested");
1006 break;
1007 }
1008}
1009
1010void
1011write_floats (std::ostream& os, const float *data, save_type type,
1013{
1014 switch (type)
1015 {
1016 case LS_U_CHAR:
1017 LS_DO_WRITE (uint8_t, data, 1, len, os);
1018 break;
1019
1020 case LS_U_SHORT:
1021 LS_DO_WRITE (uint16_t, data, 2, len, os);
1022 break;
1023
1024 case LS_U_INT:
1025 LS_DO_WRITE (uint32_t, data, 4, len, os);
1026 break;
1027
1028 case LS_CHAR:
1029 LS_DO_WRITE (int8_t, data, 1, len, os);
1030 break;
1031
1032 case LS_SHORT:
1033 LS_DO_WRITE (int16_t, data, 2, len, os);
1034 break;
1035
1036 case LS_INT:
1037 LS_DO_WRITE (int32_t, data, 4, len, os);
1038 break;
1039
1040 case LS_FLOAT: // No conversion necessary.
1041 {
1042 char tmp_type = static_cast<char> (type);
1043 os.write (&tmp_type, 1);
1044 std::streamsize n_bytes = sizeof (float) * static_cast<std::streamsize> (len);
1045 do_write (os, reinterpret_cast<const char *> (data), n_bytes);
1046 }
1047 break;
1048
1049 case LS_DOUBLE:
1050 LS_DO_WRITE (double, data, 8, len, os);
1051 break;
1052
1053 default:
1054 (*current_liboctave_error_handler)
1055 ("unrecognized data format requested");
1056 break;
1057 }
1058}
void swap_bytes< 8 >(void *ptr)
Definition byte-swap.h:71
void swap_bytes< 4 >(void *ptr)
Definition byte-swap.h:63
static std::size_t data_type_size(data_type dt)
Definition data-conv.cc:187
static std::string data_type_as_string(data_type dt)
Definition data-conv.cc:499
static data_type string_to_data_type(const std::string &s)
Definition data-conv.cc:293
void do_float_format_conversion(void *data, octave_idx_type len, octave::mach_info::float_format from_fmt, octave::mach_info::float_format to_fmt)
Definition data-conv.cc:734
#define LS_DO_READ(TYPE, swap, data, size, len, stream)
Definition data-conv.cc:606
#define FIND_SIZED_INT_TYPE(VAL, BITS, TQ, Q)
Definition data-conv.cc:69
#define GET_SIZED_INT_TYPE(T, U)
Definition data-conv.cc:158
void read_doubles(std::istream &is, double *data, save_type type, octave_idx_type len, bool swap, octave::mach_info::float_format fmt)
Definition data-conv.cc:820
void write_doubles(std::ostream &os, const double *data, save_type type, octave_idx_type len)
Definition data-conv.cc:960
void write_floats(std::ostream &os, const float *data, save_type type, octave_idx_type len)
#define LS_DO_WRITE(TYPE, data, size, len, stream)
Definition data-conv.cc:627
void read_floats(std::istream &is, float *data, save_type type, octave_idx_type len, bool swap, octave::mach_info::float_format fmt)
Definition data-conv.cc:884
void do_double_format_conversion(void *data, octave_idx_type len, octave::mach_info::float_format from_fmt, octave::mach_info::float_format to_fmt)
Definition data-conv.cc:687
#define FIND_SIZED_FLOAT_TYPE(VAL, BITS)
Definition data-conv.cc:87
save_type
Definition data-conv.h:85
@ LS_U_CHAR
Definition data-conv.h:86
@ LS_DOUBLE
Definition data-conv.h:93
@ LS_U_SHORT
Definition data-conv.h:87
@ LS_FLOAT
Definition data-conv.h:92
@ LS_SHORT
Definition data-conv.h:90
@ LS_CHAR
Definition data-conv.h:89
@ LS_INT
Definition data-conv.h:91
@ LS_U_INT
Definition data-conv.h:88
OCTAVE_NORETURN liboctave_error_handler current_liboctave_error_handler
Definition lo-error.c:41
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
Definition oct-locbuf.h:44
F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE * d
F77_RET_T len
Definition xerbla.cc:61