1// Copyright (C) 2003 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 <cstdio> 24#include <testsuite_hooks.h> 25 26template <typename InternT, typename StateT = mbstate_t> 27class checksumcvt : public std::codecvt<InternT, char, StateT> 28{ 29 typedef std::codecvt<InternT, char, StateT> Base; 30 static const size_t width = sizeof(InternT) + 1; 31 32public: 33 typedef InternT intern_type; 34 typedef char extern_type; 35 36 explicit checksumcvt(size_t refs = 0) 37 : Base(refs) 38 { } 39 40protected: 41 virtual typename std::codecvt<InternT, char, StateT>::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 = reinterpret_cast<const char*>(from); 53 unsigned char checksum = 0; 54 55 for (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<InternT, char, StateT>::ok 68 : std::codecvt<InternT, char, StateT>::partial; 69 } 70 71 virtual typename std::codecvt<InternT, char, StateT>::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<InternT, char, StateT>::ok; 77 } 78 79 virtual typename std::codecvt<InternT, char, StateT>::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 (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<InternT, char, StateT>::error : 112 (from_next == from_end ? std::codecvt<InternT, char, StateT>::ok 113 : std::codecvt<InternT, char, StateT>::partial); 114 } 115 116 virtual int 117 do_encoding() const throw() 118 { return width; } 119 120 virtual int 121 do_length(StateT&, const extern_type* from, 122 const extern_type* end, size_t max) const 123 { 124 size_t len = std::min(max, static_cast<size_t>(end - from) / width); 125 126 int ret = 0; 127 while (len--) 128 { 129 unsigned char checksum = 0; 130 131 for (size_t i = 0; i < sizeof(intern_type); ++i) 132 { 133 checksum ^= static_cast<unsigned char>(*from++); 134 } 135 136 if (*from++ != checksum) 137 break; 138 139 ret++; 140 } 141 142 return ret; 143 } 144 145 virtual int 146 do_max_length() const throw() 147 { return width; } 148 149 virtual bool 150 do_always_noconv() const throw() 151 { return false; } 152}; 153 154// libstdc++/11544 (invalid byte sequence in file) 155void test02() 156{ 157 using namespace std; 158 bool test __attribute__((unused)) = true; 159 160 locale loc(locale::classic(), new checksumcvt<wchar_t>); 161 162 const char* name = "tmp_11544-2"; 163 164 FILE* f = fopen(name, "w"); 165 fwrite("aaaab", 1, 5, f); 166 fclose(f); 167 168 wifstream in; 169 in.imbue(loc); 170 in.open(name); 171 172 VERIFY( in.good() ); 173 in.get(); 174 VERIFY( !in.good() ); 175 VERIFY( in.bad() ); 176 VERIFY( !in.eof() ); 177 178 in.close(); 179} 180 181int main() 182{ 183 test02(); 184 return 0; 185} 186