1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // REQUIRES: locale.en_US.UTF-8
10 
11 // <fstream>
12 
13 // int_type underflow();
14 
15 // This test is not entirely portable
16 
17 #include <fstream>
18 #include <cstddef>
19 #include <cassert>
20 
21 #include "platform_support.h" // locale name macros
22 
23 template <class CharT>
24 struct test_buf
25     : public std::basic_filebuf<CharT>
26 {
27     typedef std::basic_filebuf<CharT> base;
28     typedef typename base::char_type  char_type;
29     typedef typename base::int_type   int_type;
30 
31     char_type* eback() const {return base::eback();}
32     char_type* gptr()  const {return base::gptr();}
33     char_type* egptr() const {return base::egptr();}
34     void gbump(int n) {base::gbump(n);}
35 
36     virtual int_type underflow() {return base::underflow();}
37 };
38 
39 int main(int, char**)
40 {
41     {
42         test_buf<char> f;
43         assert(f.open("underflow.dat", std::ios_base::in) != 0);
44         assert(f.is_open());
45         assert(f.eback() == 0);
46         assert(f.gptr() == 0);
47         assert(f.egptr() == 0);
48         assert(f.underflow() == '1');
49         assert(f.eback() != 0);
50         assert(f.eback() == f.gptr());
51         assert(*f.gptr() == '1');
52         assert(f.egptr() - f.eback() == 9);
53     }
54     {
55         test_buf<char> f;
56         assert(f.open("underflow.dat", std::ios_base::in) != 0);
57         assert(f.pubsetbuf(0, 0));
58         assert(f.is_open());
59         assert(f.eback() == 0);
60         assert(f.gptr() == 0);
61         assert(f.egptr() == 0);
62         assert(f.underflow() == '1');
63         assert(f.eback() != 0);
64         assert(f.eback() == f.gptr());
65         assert(*f.gptr() == '1');
66         assert(f.egptr() - f.eback() == 8);
67         f.gbump(8);
68         assert(f.sgetc() == '9');
69         assert(f.eback()[0] == '5');
70         assert(f.eback()[1] == '6');
71         assert(f.eback()[2] == '7');
72         assert(f.eback()[3] == '8');
73         assert(f.gptr() - f.eback() == 4);
74         assert(*f.gptr() == '9');
75         assert(f.egptr() - f.gptr() == 1);
76     }
77     {
78         test_buf<wchar_t> f;
79         assert(f.open("underflow.dat", std::ios_base::in) != 0);
80         assert(f.is_open());
81         assert(f.eback() == 0);
82         assert(f.gptr() == 0);
83         assert(f.egptr() == 0);
84         assert(f.underflow() == L'1');
85         assert(f.eback() != 0);
86         assert(f.eback() == f.gptr());
87         assert(*f.gptr() == L'1');
88         assert(f.egptr() - f.eback() == 9);
89     }
90     {
91         test_buf<wchar_t> f;
92         assert(f.pubsetbuf(0, 0));
93         assert(f.open("underflow.dat", std::ios_base::in) != 0);
94         assert(f.is_open());
95         assert(f.eback() == 0);
96         assert(f.gptr() == 0);
97         assert(f.egptr() == 0);
98         assert(f.underflow() == L'1');
99         assert(f.eback() != 0);
100         assert(f.eback() == f.gptr());
101         assert(*f.gptr() == L'1');
102         assert(f.egptr() - f.eback() == 8);
103         f.gbump(8);
104         assert(f.sgetc() == L'9');
105         assert(f.eback()[0] == L'5');
106         assert(f.eback()[1] == L'6');
107         assert(f.eback()[2] == L'7');
108         assert(f.eback()[3] == L'8');
109         assert(f.gptr() - f.eback() == 4);
110         assert(*f.gptr() == L'9');
111         assert(f.egptr() - f.gptr() == 1);
112     }
113     {
114         typedef std::char_traits<wchar_t> Traits;
115         test_buf<wchar_t> f;
116         f.pubimbue(std::locale(LOCALE_en_US_UTF_8));
117         assert(f.open("underflow_utf8.dat", std::ios_base::in) != 0);
118         assert(f.is_open());
119         assert(f.sbumpc() == 0x4E51);
120         assert(f.sbumpc() == 0x4E52);
121         assert(f.sbumpc() == 0x4E53);
122         assert(f.sbumpc() == static_cast<Traits::int_type>(-1));
123     }
124 
125   return 0;
126 }
127