Skip to content

Commit e26f65a

Browse files
committed
Write and read large array in chunks for "-binary" file format (bug #67382).
* liboctave/util/data-conv.cc (do_read): New function that reads large amount of data in chunks of 64 MiB. (LS_DO_READ, read_doubles, read_floats): Use function "do_read" to read data from file stream. (do_write): New function that writes large amount of data in chunks of 64 MiB. (LS_DO_WRITE, write_doubles, write_floats): Use function "do_write" to write data to file stream.
1 parent e1a1dac commit e26f65a

File tree

1 file changed

+56
-13
lines changed

1 file changed

+56
-13
lines changed

liboctave/util/data-conv.cc

Lines changed: 56 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -610,7 +610,9 @@ oct_data_conv::data_type_as_string (oct_data_conv::data_type dt)
610610
{ \
611611
OCTAVE_LOCAL_BUFFER (TYPE, ptr, len); \
612612
std::streamsize n_bytes = size * static_cast<std::streamsize> (len); \
613-
stream.read (reinterpret_cast<char *> (ptr), n_bytes); \
613+
do_read (stream, reinterpret_cast<char *> (ptr), n_bytes); \
614+
if (! stream) \
615+
return; \
614616
if (swap) \
615617
swap_bytes< size > (ptr, len); \
616618
for (octave_idx_type i = 0; i < len; i++) \
@@ -633,7 +635,7 @@ oct_data_conv::data_type_as_string (oct_data_conv::data_type dt)
633635
for (octave_idx_type i = 0; i < len; i++) \
634636
ptr[i] = static_cast<TYPE> (data[i]); \
635637
std::streamsize n_bytes = size * static_cast<std::streamsize> (len); \
636-
stream.write (reinterpret_cast<char *> (ptr), n_bytes); \
638+
do_write (stream, reinterpret_cast<const char *> (ptr), n_bytes); \
637639
} \
638640
} \
639641
while (0)
@@ -798,6 +800,22 @@ do_float_format_conversion (void *data, std::size_t sz, octave_idx_type len,
798800
}
799801
}
800802

803+
static void
804+
do_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+
}
801819
void
802820
read_doubles (std::istream& is, double *data, save_type type,
803821
octave_idx_type len, bool swap,
@@ -832,8 +850,10 @@ read_doubles (std::istream& is, double *data, save_type type,
832850
case LS_FLOAT:
833851
{
834852
OCTAVE_LOCAL_BUFFER (float, ptr, len);
835-
std::streamsize n_bytes = 4 * static_cast<std::streamsize> (len);
836-
is.read (reinterpret_cast<char *> (ptr), n_bytes);
853+
std::streamsize n_bytes = sizeof (float) * static_cast<std::streamsize> (len);
854+
do_read (is, reinterpret_cast<char *> (data), n_bytes);
855+
if (! is)
856+
return;
837857
do_float_format_conversion (ptr, len, fmt);
838858
for (octave_idx_type i = 0; i < len; i++)
839859
data[i] = ptr[i];
@@ -842,8 +862,10 @@ read_doubles (std::istream& is, double *data, save_type type,
842862

843863
case LS_DOUBLE: // No conversion necessary.
844864
{
845-
std::streamsize n_bytes = 8 * static_cast<std::streamsize> (len);
846-
is.read (reinterpret_cast<char *> (data), n_bytes);
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;
847869
do_double_format_conversion (data, len, fmt);
848870
// FIXME: Potentially add conversion code for MIPS NA here, Bug #59830.
849871
//
@@ -891,8 +913,10 @@ read_floats (std::istream& is, float *data, save_type type,
891913

892914
case LS_FLOAT: // No conversion necessary.
893915
{
894-
std::streamsize n_bytes = 4 * static_cast<std::streamsize> (len);
895-
is.read (reinterpret_cast<char *> (data), n_bytes);
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;
896920
do_float_format_conversion (data, len, fmt);
897921
}
898922
break;
@@ -901,7 +925,9 @@ read_floats (std::istream& is, float *data, save_type type,
901925
{
902926
OCTAVE_LOCAL_BUFFER (double, ptr, len);
903927
std::streamsize n_bytes = 8 * static_cast<std::streamsize> (len);
904-
is.read (reinterpret_cast<char *> (ptr), n_bytes);
928+
do_read (is, reinterpret_cast<char *> (data), n_bytes);
929+
if (! is)
930+
return;
905931
do_double_format_conversion (ptr, len, fmt);
906932
for (octave_idx_type i = 0; i < len; i++)
907933
data[i] = ptr[i];
@@ -914,6 +940,22 @@ read_floats (std::istream& is, float *data, save_type type,
914940
}
915941
}
916942

943+
static void
944+
do_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+
917959
void
918960
write_doubles (std::ostream& os, const double *data, save_type type,
919961
octave_idx_type len)
@@ -952,8 +994,9 @@ write_doubles (std::ostream& os, const double *data, save_type type,
952994
{
953995
char tmp_type = static_cast<char> (type);
954996
os.write (&tmp_type, 1);
955-
std::streamsize n_bytes = 8 * static_cast<std::streamsize> (len);
956-
os.write (reinterpret_cast<const char *> (data), n_bytes);
997+
998+
std::streamsize n_bytes = sizeof (double) * static_cast<std::streamsize> (len);
999+
do_write (os, reinterpret_cast<const char *> (data), n_bytes);
9571000
}
9581001
break;
9591002

@@ -998,8 +1041,8 @@ write_floats (std::ostream& os, const float *data, save_type type,
9981041
{
9991042
char tmp_type = static_cast<char> (type);
10001043
os.write (&tmp_type, 1);
1001-
std::streamsize n_bytes = 4 * static_cast<std::streamsize> (len);
1002-
os.write (reinterpret_cast<const char *> (data), n_bytes);
1044+
std::streamsize n_bytes = sizeof (float) * static_cast<std::streamsize> (len);
1045+
do_write (os, reinterpret_cast<const char *> (data), n_bytes);
10031046
}
10041047
break;
10051048

0 commit comments

Comments
 (0)