1// Copyright (C) 2003, 2004, 2009 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// 27.8.1.4 Overridden virtual functions 19 20// { dg-require-binary-io "" } 21 22#include <fstream> 23#include <locale> 24#include <testsuite_hooks.h> 25 26template <typename InternT, typename StateT = std::mbstate_t> 27class 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 32public: 33 typedef InternT intern_type; 34 typedef char extern_type; 35 36 explicit checksumcvt(std::size_t refs = 0) 37 : Base(refs) 38 { } 39 40protected: 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 156class Buf : public std::wfilebuf 157{ 158public: 159 std::streamsize pub_showmanyc() 160 { return showmanyc(); } 161 std::wfilebuf::int_type pub_underflow() 162 { return underflow(); } 163}; 164 165// libstdc++/11603 166void test01() 167{ 168 using namespace std; 169 bool test __attribute__((unused)) = true; 170 171 filebuf fbout; 172 fbout.open("tmp_11603", ios_base::out); 173 fbout.sputn("aaaab", 5); 174 fbout.close(); 175 176 locale loc(locale::classic(), new checksumcvt<wchar_t>); 177 178 Buf fb; 179 fb.pubimbue(loc); 180 fb.open("tmp_11603", ios_base::in); 181 VERIFY( fb.pub_showmanyc() == 1 ); 182 183 try 184 { 185 wfilebuf::int_type ret = fb.pub_underflow(); 186 VERIFY( ret != wfilebuf::traits_type::eof() ); 187 fb.sbumpc(); 188 ret = fb.pub_underflow(); 189 VERIFY( ret == wfilebuf::traits_type::eof() ); 190 } 191 catch (...) 192 { } 193 194 fb.close(); 195} 196 197int main() 198{ 199 test01(); 200 return 0; 201} 202