1// Copyright (C) 2003, 2004 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 2, 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 COPYING. If not, write to the Free 16// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 17// USA. 18 19// 27.8.1.4 Overridden virtual functions 20 21#include <fstream> 22#include <locale> 23#include <testsuite_hooks.h> 24 25template <typename InternT, typename StateT = std::mbstate_t> 26class checksumcvt : public std::codecvt<InternT, char, StateT> 27{ 28 typedef std::codecvt<InternT, char, StateT> Base; 29 static const std::size_t width = sizeof(InternT) + 1; 30 31public: 32 typedef InternT intern_type; 33 typedef char extern_type; 34 35 explicit checksumcvt(std::size_t refs = 0) 36 : Base(refs) 37 { } 38 39protected: 40 virtual std::codecvt_base::result 41 do_out(StateT&, const intern_type* from, 42 const intern_type* from_end, const intern_type*& from_next, 43 extern_type* to, extern_type* to_end, 44 extern_type*& to_next) const 45 { 46 size_t len = std::min(static_cast<size_t>(from_end - from), 47 static_cast<size_t>(to_end - to) / width); 48 49 while (len--) 50 { 51 const char* p = 52 reinterpret_cast<const char*>(from); 53 unsigned char checksum = 0; 54 55 for (std::size_t i = 0; i < sizeof(intern_type); ++i) 56 { 57 *to++ = p[i]; 58 checksum ^= static_cast<unsigned char>(p[i]); 59 } 60 61 *to++ = checksum; 62 ++from; 63 } 64 65 from_next = from; 66 to_next = to; 67 return from_next == from_end ? std::codecvt_base::ok 68 : std::codecvt_base::partial; 69 } 70 71 virtual std::codecvt_base::result 72 do_unshift(StateT&, extern_type* to, 73 extern_type*, extern_type*& to_next) const 74 { 75 to_next = to; 76 return std::codecvt_base::ok; 77 } 78 79 virtual std::codecvt_base::result 80 do_in(StateT&, const extern_type* from, 81 const extern_type* from_end, const extern_type*& from_next, 82 intern_type* to, intern_type* to_end, 83 intern_type*& to_next) const 84 { 85 size_t len = std::min(static_cast<size_t>(to_end - to), 86 static_cast<size_t>(from_end - from) / width); 87 88 while (len) 89 { 90 const char* f = from; 91 intern_type tmp; 92 char* p = reinterpret_cast<char*>(&tmp); 93 unsigned char checksum = 0; 94 95 for (std::size_t i = 0; i < sizeof(intern_type); ++i) 96 { 97 p[i] = *f; 98 checksum ^= static_cast<unsigned char>(*f++); 99 } 100 101 if (*f++ != checksum) 102 break; 103 104 from = f; 105 *to++ = tmp; 106 len--; 107 } 108 109 from_next = from; 110 to_next = to; 111 return len ? std::codecvt_base::error : 112 (from_next == from_end ? std::codecvt_base::ok 113 : std::codecvt_base::partial); 114 } 115 116 virtual int 117 do_encoding() const throw() 118 { return width; } 119 120 virtual int 121 do_length(const StateT&, const extern_type* from, 122 const extern_type* end, size_t max) const 123 { 124 size_t len = std::min(max, 125 static_cast<size_t>(end - from) / width); 126 127 int ret = 0; 128 while (len--) 129 { 130 unsigned char checksum = 0; 131 132 for (std::size_t i = 0; i < sizeof(intern_type); ++i) 133 { 134 checksum ^= static_cast<unsigned char>(*from++); 135 } 136 137 if (*from++ != checksum) 138 break; 139 140 ret++; 141 } 142 143 return ret; 144 } 145 146 virtual int 147 do_max_length() const throw() 148 { return width; } 149 150 virtual bool 151 do_always_noconv() const throw() 152 { return false; } 153}; 154 155class Buf : public std::wfilebuf 156{ 157public: 158 std::streamsize pub_showmanyc() 159 { return showmanyc(); } 160 std::wfilebuf::int_type pub_underflow() 161 { return underflow(); } 162}; 163 164// libstdc++/11603 165void test01() 166{ 167 using namespace std; 168 bool test __attribute__((unused)) = true; 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); 180 VERIFY( fb.pub_showmanyc() == 1 ); 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 196int main() 197{ 198 test01(); 199 return 0; 200} 201