# HG changeset patch # User John W. Eaton # Date 1396569014 14400 # Node ID aa861a98d84d084656ef9109bfd5279fea82aa99 # Parent ef7bb00d8167d84326ac30427f499a0e47c573b4 fwrite: don't convert to octave_int for char output types * oct-stream.cc (convert_chars): New template function. (ultimate_element_type): New traits class and specialization. (convert_data): Handle conversion to char types differently from single byte integer types. * io.tst: New test. diff -r ef7bb00d8167 -r aa861a98d84d libinterp/corefcn/oct-stream.cc --- a/libinterp/corefcn/oct-stream.cc Tue Apr 01 15:49:23 2014 +0200 +++ b/libinterp/corefcn/oct-stream.cc Thu Apr 03 19:50:14 2014 -0400 @@ -3379,6 +3379,18 @@ template static void +convert_chars (const void *data, void *conv_data, octave_idx_type n_elts) +{ + const T *tt_data = static_cast (data); + + V *vt_data = static_cast (conv_data); + + for (octave_idx_type i = 0; i < n_elts; i++) + vt_data[i] = tt_data[i]; +} + +template +static void convert_ints (const T *data, void *conv_data, octave_idx_type n_elts, bool swap) { @@ -3388,6 +3400,9 @@ for (octave_idx_type i = 0; i < n_elts; i++) { + // Yes, we want saturation semantics when converting to an integer + // type. + V val (data[i]); vt_data[i] = val.value (); @@ -3398,6 +3413,20 @@ } template +class ultimate_element_type +{ +public: + typedef T type; +}; + +template +class ultimate_element_type > +{ +public: + typedef T type; +}; + +template static bool convert_data (const T *data, void *conv_data, octave_idx_type n_elts, oct_data_conv::data_type output_type, @@ -3412,18 +3441,26 @@ bool do_float_conversion = flt_fmt != oct_mach_info::float_format (); - // We use octave_intN classes here instead of converting directly to - // intN_t so that we get integer saturation semantics. + typedef typename ultimate_element_type::type ult_elt_type; switch (output_type) { case oct_data_conv::dt_char: + convert_chars (data, conv_data, n_elts); + break; + case oct_data_conv::dt_schar: + convert_chars (data, conv_data, n_elts); + break; + + case oct_data_conv::dt_uchar: + convert_chars (data, conv_data, n_elts); + break; + case oct_data_conv::dt_int8: convert_ints (data, conv_data, n_elts, swap); break; - case oct_data_conv::dt_uchar: case oct_data_conv::dt_uint8: convert_ints (data, conv_data, n_elts, swap); break; diff -r ef7bb00d8167 -r aa861a98d84d test/io.tst --- a/test/io.tst Tue Apr 01 15:49:23 2014 +0200 +++ b/test/io.tst Thu Apr 03 19:50:14 2014 -0400 @@ -434,6 +434,18 @@ %! assert (__prog_output_assert__ ("ok")); %!test +%! x = char (128:255)'; +%! nm = tmpnam (); +%! id = fopen (nm, "wb"); +%! fwrite (id, x); +%! fclose (id); +%! id = fopen (nm, "rb"); +%! y = fread (id, Inf, "uchar=>char"); +%! fclose (id); +%! unlink (nm); +%! assert (x, y); + +%!test %! nm = tmpnam (); %! id = fopen (nm, "wb"); %! if (id > 0)