]> git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/testsuite/27_io/basic_istream/ignore/char/94749.cc
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / testsuite / 27_io / basic_istream / ignore / char / 94749.cc
1 // Copyright (C) 2020-2022 Free Software Foundation, Inc.
2 //
3 // This file is part of the GNU ISO C++ Library. This library is free
4 // software; you can redistribute it and/or modify it under the
5 // terms of the GNU General Public License as published by the
6 // Free Software Foundation; either version 3, or (at your option)
7 // any later version.
8
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13
14 // You should have received a copy of the GNU General Public License along
15 // with this library; see the file COPYING3. If not see
16 // <http://www.gnu.org/licenses/>.
17
18 // { dg-do run }
19 // { dg-options "-DSIMULATOR_TEST" { target simulator } }
20 // { dg-timeout-factor 2 { target ilp32 } }
21
22 // PR libstdc++/94749
23 // basic_istream::ignore(n, c) discards n+1 if next character is equal to c.
24
25 #include <sstream>
26 #include <limits>
27 #include <testsuite_hooks.h>
28
29 typedef char C;
30
31 void
32 test01()
33 {
34 std::basic_istringstream<C> s(" + -");
35 s.ignore(1, '+');
36 VERIFY( s.gcount() == 1 );
37 VERIFY( s.get() == '+' );
38 s.ignore(3, '-');
39 VERIFY( s.gcount() == 3 );
40 VERIFY( s.get() == '-' );
41 }
42
43 void
44 test02()
45 {
46 std::basic_istringstream<C> s(".+...-");
47 s.ignore(1, '+');
48 VERIFY( s.gcount() == 1 );
49 VERIFY( s.get() == '+' );
50 s.ignore(3, '-');
51 VERIFY( s.gcount() == 3 );
52 VERIFY( s.get() == '-' );
53 }
54
55 void
56 test03()
57 {
58 std::basic_istringstream<C, __gnu_cxx::char_traits<C> > s(" + -");
59 s.ignore(1, '+');
60 VERIFY( s.gcount() == 1 );
61 VERIFY( s.get() == '+' );
62 s.ignore(3, '-');
63 VERIFY( s.gcount() == 3 );
64 VERIFY( s.get() == '-' );
65 }
66
67 void
68 test04()
69 {
70 std::basic_istringstream<C, __gnu_cxx::char_traits<C> > s(".+...-");
71 s.ignore(1, '+');
72 VERIFY( s.gcount() == 1 );
73 VERIFY( s.get() == '+' );
74 s.ignore(3, '-');
75 VERIFY( s.gcount() == 3 );
76 VERIFY( s.get() == '-' );
77 }
78
79 // The original fix for PR libstdc++/94749 failed to discard the delimiter
80 // if it occurred after numeric_limits<streamsize>::max() had been seen.
81 // This streambuf will keep filling the get area with zero bytes until
82 // almost numeric_limits<streamsize>::max() characters have been read,
83 // and then return one more buffer that has "123" at its end.
84 template<typename T>
85 struct buff : std::basic_streambuf<typename T::char_type, T>
86 {
87 typedef typename T::char_type char_type;
88 typedef typename T::int_type int_type;
89 typedef std::streamsize streamsize;
90 typedef std::numeric_limits<streamsize> limits;
91
92 buff() : count(0), buf() { }
93
94 int_type underflow()
95 {
96 // Number of characters left until we overflow the counter
97 const streamsize headroom = limits::max() - count;
98
99 if (headroom == 0)
100 return T::eof();
101
102 if (bufsz < headroom)
103 {
104 this->setg(buf, buf, buf + bufsz);
105 count += bufsz;
106 }
107 else
108 {
109 // write "123" across the 2GB boundary
110 buf[headroom-1] = '1';
111 buf[headroom+0] = '2';
112 buf[headroom+1] = '3';
113 this->setg(buf, buf, buf + headroom + 2);
114 count = limits::max();
115 }
116
117 return buf[0];
118 }
119
120 streamsize count;
121
122 static const streamsize bufsz = 2048 << limits::digits10;
123 char_type buf[bufsz + 2];
124 };
125
126 void
127 test05()
128 {
129 // Not possible to overflow 64-bit streamsize in reasonable time.
130 if (std::numeric_limits<std::streamsize>::digits > 32)
131 return;
132
133 typedef std::char_traits<C> T;
134
135 std::basic_istream<C, T> in(new buff<T>);
136
137 in.ignore(std::numeric_limits<std::streamsize>::max(), '1');
138 VERIFY(in.good());
139 VERIFY(in.gcount() == std::numeric_limits<std::streamsize>::max());
140 VERIFY(in.get() == '2');
141 VERIFY(in.get() == '3');
142 VERIFY(in.get() == T::eof());
143
144 delete in.rdbuf(new buff<T>);
145
146 in.ignore(std::numeric_limits<std::streamsize>::max(), '2');
147 VERIFY(in.good());
148 // The standard doesn't say what gcount() should return in this case:
149 VERIFY(in.gcount() == std::numeric_limits<std::streamsize>::max());
150 VERIFY(in.get() == '3');
151 VERIFY(in.get() == T::eof());
152
153 delete in.rdbuf(new buff<T>);
154
155 in.ignore(std::numeric_limits<std::streamsize>::max(), '3');
156 VERIFY(in.good());
157 // The standard doesn't say what gcount() should return in this case:
158 VERIFY(in.gcount() == std::numeric_limits<std::streamsize>::max());
159 VERIFY(in.get() == T::eof());
160
161 delete in.rdbuf(new buff<T>);
162
163 in.ignore(std::numeric_limits<std::streamsize>::max(), '4');
164 VERIFY(in.eof());
165 // The standard doesn't say what gcount() should return in this case:
166 VERIFY(in.gcount() == std::numeric_limits<std::streamsize>::max());
167 VERIFY(in.get() == T::eof());
168
169 delete in.rdbuf(0);
170 }
171
172 void
173 test06()
174 {
175 if (std::numeric_limits<std::streamsize>::digits > 32)
176 return;
177
178 typedef __gnu_cxx::char_traits<C> T;
179
180 std::basic_istream<C, T> in(new buff<T>);
181
182 in.ignore(std::numeric_limits<std::streamsize>::max(), '1');
183 VERIFY(in.good());
184 VERIFY(in.gcount() == std::numeric_limits<std::streamsize>::max());
185 VERIFY(in.get() == '2');
186 VERIFY(in.get() == '3');
187 VERIFY(in.get() == T::eof());
188
189 delete in.rdbuf(new buff<T>);
190
191 in.ignore(std::numeric_limits<std::streamsize>::max(), '2');
192 VERIFY(in.good());
193 // The standard doesn't say what gcount() should return in this case:
194 VERIFY(in.gcount() == std::numeric_limits<std::streamsize>::max());
195 VERIFY(in.get() == '3');
196 VERIFY(in.get() == T::eof());
197
198 delete in.rdbuf(new buff<T>);
199
200 in.ignore(std::numeric_limits<std::streamsize>::max(), '3');
201 VERIFY(in.good());
202 // The standard doesn't say what gcount() should return in this case:
203 VERIFY(in.gcount() == std::numeric_limits<std::streamsize>::max());
204 VERIFY(in.get() == T::eof());
205
206 delete in.rdbuf(new buff<T>);
207
208 in.ignore(std::numeric_limits<std::streamsize>::max(), '4');
209 VERIFY(in.eof());
210 // The standard doesn't say what gcount() should return in this case:
211 VERIFY(in.gcount() == std::numeric_limits<std::streamsize>::max());
212 VERIFY(in.get() == T::eof());
213
214 delete in.rdbuf(0);
215 }
216
217 int
218 main()
219 {
220 test01();
221 test02();
222 test03();
223 test04();
224 test05();
225 #ifndef SIMULATOR_TEST
226 test06();
227 #endif
228 }