]>
Commit | Line | Data |
---|---|---|
7adcbafe | 1 | // Copyright (C) 2003-2022 Free Software Foundation, Inc. |
5536b61c PC |
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 | |
748086b7 | 6 | // Free Software Foundation; either version 3, or (at your option) |
5536b61c PC |
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 | |
748086b7 JJ |
15 | // with this library; see the file COPYING3. If not see |
16 | // <http://www.gnu.org/licenses/>. | |
5536b61c PC |
17 | |
18 | // 27.8.1.4 Overridden virtual functions | |
19 | ||
f16fd827 JM |
20 | // { dg-require-binary-io "" } |
21 | ||
5536b61c PC |
22 | #include <fstream> |
23 | #include <locale> | |
24 | #include <testsuite_hooks.h> | |
25 | ||
26 | template <typename InternT, typename StateT = std::mbstate_t> | |
27 | class checksumcvt : public std::codecvt<InternT, char, StateT> | |
28 | { | |
29 | typedef std::codecvt<InternT, char, StateT> Base; | |
30 | static const std::size_t width = sizeof(InternT) + 1; | |
31 | ||
32 | public: | |
33 | typedef InternT intern_type; | |
34 | typedef char extern_type; | |
35 | ||
36 | explicit checksumcvt(std::size_t refs = 0) | |
37 | : Base(refs) | |
38 | { } | |
39 | ||
40 | protected: | |
41 | virtual std::codecvt_base::result | |
42 | do_out(StateT&, const intern_type* from, | |
43 | const intern_type* from_end, const intern_type*& from_next, | |
44 | extern_type* to, extern_type* to_end, | |
45 | extern_type*& to_next) const | |
46 | { | |
47 | size_t len = std::min(static_cast<size_t>(from_end - from), | |
48 | static_cast<size_t>(to_end - to) / width); | |
49 | ||
50 | while (len--) | |
51 | { | |
52 | const char* p = | |
53 | reinterpret_cast<const char*>(from); | |
54 | unsigned char checksum = 0; | |
55 | ||
56 | for (std::size_t i = 0; i < sizeof(intern_type); ++i) | |
57 | { | |
58 | *to++ = p[i]; | |
59 | checksum ^= static_cast<unsigned char>(p[i]); | |
60 | } | |
61 | ||
62 | *to++ = checksum; | |
63 | ++from; | |
64 | } | |
65 | ||
66 | from_next = from; | |
67 | to_next = to; | |
68 | return from_next == from_end ? std::codecvt_base::ok | |
69 | : std::codecvt_base::partial; | |
70 | } | |
71 | ||
72 | virtual std::codecvt_base::result | |
73 | do_unshift(StateT&, extern_type* to, | |
74 | extern_type*, extern_type*& to_next) const | |
75 | { | |
76 | to_next = to; | |
77 | return std::codecvt_base::ok; | |
78 | } | |
79 | ||
80 | virtual std::codecvt_base::result | |
81 | do_in(StateT&, const extern_type* from, | |
82 | const extern_type* from_end, const extern_type*& from_next, | |
83 | intern_type* to, intern_type* to_end, | |
84 | intern_type*& to_next) const | |
85 | { | |
86 | size_t len = std::min(static_cast<size_t>(to_end - to), | |
87 | static_cast<size_t>(from_end - from) / width); | |
88 | ||
89 | while (len) | |
90 | { | |
91 | const char* f = from; | |
92 | intern_type tmp; | |
93 | char* p = reinterpret_cast<char*>(&tmp); | |
94 | unsigned char checksum = 0; | |
95 | ||
96 | for (std::size_t i = 0; i < sizeof(intern_type); ++i) | |
97 | { | |
98 | p[i] = *f; | |
99 | checksum ^= static_cast<unsigned char>(*f++); | |
100 | } | |
101 | ||
102 | if (*f++ != checksum) | |
103 | break; | |
104 | ||
105 | from = f; | |
106 | *to++ = tmp; | |
107 | len--; | |
108 | } | |
109 | ||
110 | from_next = from; | |
111 | to_next = to; | |
112 | return len ? std::codecvt_base::error : | |
113 | (from_next == from_end ? std::codecvt_base::ok | |
114 | : std::codecvt_base::partial); | |
115 | } | |
116 | ||
117 | virtual int | |
118 | do_encoding() const throw() | |
119 | { return width; } | |
120 | ||
121 | virtual int | |
122 | do_length(const StateT&, const extern_type* from, | |
123 | const extern_type* end, size_t max) const | |
124 | { | |
125 | size_t len = std::min(max, | |
126 | static_cast<size_t>(end - from) / width); | |
127 | ||
128 | int ret = 0; | |
129 | while (len--) | |
130 | { | |
131 | unsigned char checksum = 0; | |
132 | ||
133 | for (std::size_t i = 0; i < sizeof(intern_type); ++i) | |
134 | { | |
135 | checksum ^= static_cast<unsigned char>(*from++); | |
136 | } | |
137 | ||
138 | if (*from++ != checksum) | |
139 | break; | |
140 | ||
141 | ret++; | |
142 | } | |
143 | ||
144 | return ret; | |
145 | } | |
146 | ||
147 | virtual int | |
148 | do_max_length() const throw() | |
149 | { return width; } | |
150 | ||
151 | virtual bool | |
152 | do_always_noconv() const throw() | |
153 | { return false; } | |
154 | }; | |
155 | ||
156 | class Buf : public std::wfilebuf | |
157 | { | |
158 | public: | |
159 | std::streamsize pub_showmanyc() | |
160 | { return showmanyc(); } | |
161 | std::wfilebuf::int_type pub_underflow() | |
162 | { return underflow(); } | |
163 | }; | |
164 | ||
165 | // libstdc++/11603 | |
166 | void test01() | |
167 | { | |
168 | using namespace std; | |
5536b61c PC |
169 | |
170 | filebuf fbout; | |
171 | fbout.open("tmp_11603", ios_base::out); | |
172 | fbout.sputn("aaaab", 5); | |
173 | fbout.close(); | |
174 | ||
175 | locale loc(locale::classic(), new checksumcvt<wchar_t>); | |
176 | ||
177 | Buf fb; | |
178 | fb.pubimbue(loc); | |
179 | fb.open("tmp_11603", ios_base::in); | |
fcfbdb74 | 180 | VERIFY( fb.pub_showmanyc() == 1 ); |
5536b61c PC |
181 | |
182 | try | |
183 | { | |
184 | wfilebuf::int_type ret = fb.pub_underflow(); | |
185 | VERIFY( ret != wfilebuf::traits_type::eof() ); | |
186 | fb.sbumpc(); | |
187 | ret = fb.pub_underflow(); | |
188 | VERIFY( ret == wfilebuf::traits_type::eof() ); | |
189 | } | |
190 | catch (...) | |
191 | { } | |
192 | ||
193 | fb.close(); | |
194 | } | |
195 | ||
196 | int main() | |
197 | { | |
198 | test01(); | |
199 | return 0; | |
200 | } |