]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/testsuite/27_io/basic_istream/ignore/wchar_t/94749.cc
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / testsuite / 27_io / basic_istream / ignore / wchar_t / 94749.cc
CommitLineData
99dee823 1// Copyright (C) 2020-2021 Free Software Foundation, Inc.
b32eea9c
JW
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 }
ba8fe4b4 19// { dg-options "-DSIMULATOR_TEST" { target simulator } }
8b2c3b5a 20// { dg-timeout-factor 2 { target ilp32 } }
b32eea9c
JW
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>
ba8fe4b4 26#include <limits>
b32eea9c
JW
27#include <testsuite_hooks.h>
28
29typedef wchar_t C;
30
31void
32test01()
33{
34 std::basic_istringstream<C> s(L" + -");
35 s.ignore(1, L'+');
ba8fe4b4 36 VERIFY( s.gcount() == 1 );
b32eea9c
JW
37 VERIFY( s.get() == L'+' );
38 s.ignore(3, L'-');
ba8fe4b4 39 VERIFY( s.gcount() == 3 );
b32eea9c
JW
40 VERIFY( s.get() == L'-' );
41}
42
43void
44test02()
45{
46 std::basic_istringstream<C> s(L".+...-");
47 s.ignore(1, L'+');
ba8fe4b4 48 VERIFY( s.gcount() == 1 );
b32eea9c
JW
49 VERIFY( s.get() == L'+' );
50 s.ignore(3, L'-');
ba8fe4b4 51 VERIFY( s.gcount() == 3 );
b32eea9c
JW
52 VERIFY( s.get() == L'-' );
53}
54
55void
56test03()
57{
58 std::basic_istringstream<C, __gnu_cxx::char_traits<C> > s(L" + -");
59 s.ignore(1, L'+');
ba8fe4b4 60 VERIFY( s.gcount() == 1 );
b32eea9c
JW
61 VERIFY( s.get() == L'+' );
62 s.ignore(3, L'-');
ba8fe4b4 63 VERIFY( s.gcount() == 3 );
b32eea9c
JW
64 VERIFY( s.get() == L'-' );
65}
66
67void
68test04()
69{
70 std::basic_istringstream<C, __gnu_cxx::char_traits<C> > s(L".+...-");
71 s.ignore(1, L'+');
ba8fe4b4 72 VERIFY( s.gcount() == 1 );
b32eea9c
JW
73 VERIFY( s.get() == L'+' );
74 s.ignore(3, L'-');
ba8fe4b4 75 VERIFY( s.gcount() == 3 );
b32eea9c
JW
76 VERIFY( s.get() == L'-' );
77}
78
ba8fe4b4
JW
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 L"123" at its end.
84template<typename T>
85struct 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 L"123" across the 2GB boundary
110 buf[headroom-1] = L'1';
111 buf[headroom+0] = L'2';
112 buf[headroom+1] = L'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
126void
127test05()
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(), L'1');
138 VERIFY(in.good());
139 VERIFY(in.gcount() == std::numeric_limits<std::streamsize>::max());
140 VERIFY(in.get() == L'2');
141 VERIFY(in.get() == L'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(), L'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() == L'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(), L'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(), L'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
8011f718 169 delete in.rdbuf(0);
ba8fe4b4
JW
170}
171
172void
173test06()
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(), L'1');
183 VERIFY(in.good());
184 VERIFY(in.gcount() == std::numeric_limits<std::streamsize>::max());
185 VERIFY(in.get() == L'2');
186 VERIFY(in.get() == L'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(), L'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() == L'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(), L'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(), L'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
8011f718 214 delete in.rdbuf(0);
ba8fe4b4 215}
b32eea9c
JW
216
217int
218main()
219{
ba8fe4b4
JW
220 test01();
221 test02();
b32eea9c
JW
222 test03();
223 test04();
ba8fe4b4
JW
224 test05();
225#ifndef SIMULATOR_TEST
226 test06();
227#endif
b32eea9c 228}