@@ -916,48 +916,52 @@ static bool EditListDirectedCharacterInput(
916
916
}
917
917
918
918
template <typename CHAR>
919
- bool EditCharacterInput (
920
- IoStatementState &io, const DataEdit &edit, CHAR *x, std::size_t length ) {
919
+ bool EditCharacterInput (IoStatementState &io, const DataEdit &edit, CHAR *x,
920
+ std::size_t lengthChars ) {
921
921
switch (edit.descriptor ) {
922
922
case DataEdit::ListDirected:
923
- return EditListDirectedCharacterInput (io, x, length , edit);
923
+ return EditListDirectedCharacterInput (io, x, lengthChars , edit);
924
924
case ' A' :
925
925
case ' G' :
926
926
break ;
927
927
case ' B' :
928
- return EditBOZInput<1 >(io, edit, x, length * sizeof *x);
928
+ return EditBOZInput<1 >(io, edit, x, lengthChars * sizeof *x);
929
929
case ' O' :
930
- return EditBOZInput<3 >(io, edit, x, length * sizeof *x);
930
+ return EditBOZInput<3 >(io, edit, x, lengthChars * sizeof *x);
931
931
case ' Z' :
932
- return EditBOZInput<4 >(io, edit, x, length * sizeof *x);
932
+ return EditBOZInput<4 >(io, edit, x, lengthChars * sizeof *x);
933
933
default :
934
934
io.GetIoErrorHandler ().SignalError (IostatErrorInFormat,
935
935
" Data edit descriptor '%c' may not be used with a CHARACTER data item" ,
936
936
edit.descriptor );
937
937
return false ;
938
938
}
939
939
const ConnectionState &connection{io.GetConnectionState ()};
940
- std::size_t remaining{length};
940
+ std::size_t remainingChars{lengthChars};
941
+ // Skip leading characters.
942
+ // Their bytes don't count towards INQUIRE(IOLENGTH=).
943
+ std::size_t skipChars{0 };
941
944
if (edit.width && *edit.width > 0 ) {
942
- remaining = *edit.width ;
945
+ remainingChars = *edit.width ;
946
+ if (remainingChars > lengthChars) {
947
+ skipChars = remainingChars - lengthChars;
948
+ }
943
949
}
944
950
// When the field is wider than the variable, we drop the leading
945
951
// characters. When the variable is wider than the field, there can be
946
952
// trailing padding or an EOR condition.
947
953
const char *input{nullptr };
948
- std::size_t ready{0 };
949
- // Skip leading bytes.
950
- // These bytes don't count towards INQUIRE(IOLENGTH=).
951
- std::size_t skip{remaining > length ? remaining - length : 0 };
954
+ std::size_t readyBytes{0 };
952
955
// Transfer payload bytes; these do count.
953
- while (remaining > 0 ) {
954
- if (ready == 0 ) {
955
- ready = io.GetNextInputBytes (input);
956
- if (ready == 0 || (ready < remaining && edit.modes .nonAdvancing )) {
957
- if (io.CheckForEndOfRecord (ready)) {
958
- if (ready == 0 ) {
956
+ while (remainingChars > 0 ) {
957
+ if (readyBytes == 0 ) {
958
+ readyBytes = io.GetNextInputBytes (input);
959
+ if (readyBytes == 0 ||
960
+ (readyBytes < remainingChars && edit.modes .nonAdvancing )) {
961
+ if (io.CheckForEndOfRecord (readyBytes)) {
962
+ if (readyBytes == 0 ) {
959
963
// PAD='YES' and no more data
960
- std::fill_n (x, length , ' ' );
964
+ std::fill_n (x, lengthChars , ' ' );
961
965
return !io.GetIoErrorHandler ().InError ();
962
966
} else {
963
967
// Do partial read(s) then pad on last iteration
@@ -967,63 +971,64 @@ bool EditCharacterInput(
967
971
}
968
972
}
969
973
}
970
- std::size_t chunk;
971
- bool skipping{skip > 0 };
974
+ std::size_t chunkBytes;
975
+ std::size_t chunkChars{1 };
976
+ bool skipping{skipChars > 0 };
972
977
if (connection.isUTF8 ) {
973
- chunk = MeasureUTF8Bytes (*input);
978
+ chunkBytes = MeasureUTF8Bytes (*input);
974
979
if (skipping) {
975
- --skip ;
980
+ --skipChars ;
976
981
} else if (auto ucs{DecodeUTF8 (input)}) {
977
982
*x++ = *ucs;
978
- --length ;
979
- } else if (chunk == 0 ) {
983
+ --lengthChars ;
984
+ } else if (chunkBytes == 0 ) {
980
985
// error recovery: skip bad encoding
981
- chunk = 1 ;
986
+ chunkBytes = 1 ;
982
987
}
983
- --remaining;
984
988
} else if (connection.internalIoCharKind > 1 ) {
985
989
// Reading from non-default character internal unit
986
- chunk = connection.internalIoCharKind ;
990
+ chunkBytes = connection.internalIoCharKind ;
987
991
if (skipping) {
988
- --skip ;
992
+ --skipChars ;
989
993
} else {
990
994
char32_t buffer{0 };
991
- std::memcpy (&buffer, input, chunk );
995
+ std::memcpy (&buffer, input, chunkBytes );
992
996
*x++ = buffer;
993
- --length ;
997
+ --lengthChars ;
994
998
}
995
- --remaining;
996
999
} else if constexpr (sizeof *x > 1 ) {
997
1000
// Read single byte with expansion into multi-byte CHARACTER
998
- chunk = 1 ;
1001
+ chunkBytes = 1 ;
999
1002
if (skipping) {
1000
- --skip ;
1003
+ --skipChars ;
1001
1004
} else {
1002
1005
*x++ = static_cast <unsigned char >(*input);
1003
- --length ;
1006
+ --lengthChars ;
1004
1007
}
1005
- --remaining;
1006
1008
} else { // single bytes -> default CHARACTER
1007
1009
if (skipping) {
1008
- chunk = std::min<std::size_t >(skip, ready);
1009
- skip -= chunk;
1010
+ chunkBytes = std::min<std::size_t >(skipChars, readyBytes);
1011
+ chunkChars = chunkBytes;
1012
+ skipChars -= chunkChars;
1010
1013
} else {
1011
- chunk = std::min<std::size_t >(remaining, ready);
1012
- std::memcpy (x, input, chunk);
1013
- x += chunk;
1014
- length -= chunk;
1014
+ chunkBytes = std::min<std::size_t >(remainingChars, readyBytes);
1015
+ chunkBytes = std::min<std::size_t >(lengthChars, chunkBytes);
1016
+ chunkChars = chunkBytes;
1017
+ std::memcpy (x, input, chunkBytes);
1018
+ x += chunkBytes;
1019
+ lengthChars -= chunkChars;
1015
1020
}
1016
- remaining -= chunk;
1017
1021
}
1018
- input += chunk;
1022
+ input += chunkBytes;
1023
+ remainingChars -= chunkChars;
1019
1024
if (!skipping) {
1020
- io.GotChar (chunk );
1025
+ io.GotChar (chunkBytes );
1021
1026
}
1022
- io.HandleRelativePosition (chunk );
1023
- ready -= chunk ;
1027
+ io.HandleRelativePosition (chunkBytes );
1028
+ readyBytes -= chunkBytes ;
1024
1029
}
1025
1030
// Pad the remainder of the input variable, if any.
1026
- std::fill_n (x, length , ' ' );
1031
+ std::fill_n (x, lengthChars , ' ' );
1027
1032
return CheckCompleteListDirectedField (io, edit);
1028
1033
}
1029
1034
0 commit comments