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