@@ -879,7 +879,8 @@ int is_null_stream_filter(struct stream_filter *filter)
879
879
880
880
struct lf_to_crlf_filter {
881
881
struct stream_filter filter ;
882
- unsigned want_lf :1 ;
882
+ unsigned has_held :1 ;
883
+ char held ;
883
884
};
884
885
885
886
static int lf_to_crlf_filter_fn (struct stream_filter * filter ,
@@ -889,10 +890,14 @@ static int lf_to_crlf_filter_fn(struct stream_filter *filter,
889
890
size_t count , o = 0 ;
890
891
struct lf_to_crlf_filter * lf_to_crlf = (struct lf_to_crlf_filter * )filter ;
891
892
892
- /* Output a pending LF if we need to */
893
- if (lf_to_crlf -> want_lf ) {
894
- output [o ++ ] = '\n' ;
895
- lf_to_crlf -> want_lf = 0 ;
893
+ /*
894
+ * We may be holding onto the CR to see if it is followed by a
895
+ * LF, in which case we would need to go to the main loop.
896
+ * Otherwise, just emit it to the output stream.
897
+ */
898
+ if (lf_to_crlf -> has_held && (lf_to_crlf -> held != '\r' || !input )) {
899
+ output [o ++ ] = lf_to_crlf -> held ;
900
+ lf_to_crlf -> has_held = 0 ;
896
901
}
897
902
898
903
/* We are told to drain */
@@ -902,22 +907,57 @@ static int lf_to_crlf_filter_fn(struct stream_filter *filter,
902
907
}
903
908
904
909
count = * isize_p ;
905
- if (count ) {
910
+ if (count || lf_to_crlf -> has_held ) {
906
911
size_t i ;
912
+ int was_cr = 0 ;
913
+
914
+ if (lf_to_crlf -> has_held ) {
915
+ was_cr = 1 ;
916
+ lf_to_crlf -> has_held = 0 ;
917
+ }
918
+
907
919
for (i = 0 ; o < * osize_p && i < count ; i ++ ) {
908
920
char ch = input [i ];
921
+
909
922
if (ch == '\n' ) {
910
923
output [o ++ ] = '\r' ;
911
- if (o >= * osize_p ) {
912
- lf_to_crlf -> want_lf = 1 ;
913
- continue ; /* We need to increase i */
914
- }
924
+ } else if (was_cr ) {
925
+ /*
926
+ * Previous round saw CR and it is not followed
927
+ * by a LF; emit the CR before processing the
928
+ * current character.
929
+ */
930
+ output [o ++ ] = '\r' ;
915
931
}
932
+
933
+ /*
934
+ * We may have consumed the last output slot,
935
+ * in which case we need to break out of this
936
+ * loop; hold the current character before
937
+ * returning.
938
+ */
939
+ if (* osize_p <= o ) {
940
+ lf_to_crlf -> has_held = 1 ;
941
+ lf_to_crlf -> held = ch ;
942
+ continue ; /* break but increment i */
943
+ }
944
+
945
+ if (ch == '\r' ) {
946
+ was_cr = 1 ;
947
+ continue ;
948
+ }
949
+
950
+ was_cr = 0 ;
916
951
output [o ++ ] = ch ;
917
952
}
918
953
919
954
* osize_p -= o ;
920
955
* isize_p -= i ;
956
+
957
+ if (!lf_to_crlf -> has_held && was_cr ) {
958
+ lf_to_crlf -> has_held = 1 ;
959
+ lf_to_crlf -> held = '\r' ;
960
+ }
921
961
}
922
962
return 0 ;
923
963
}
0 commit comments