1// Copyright (C) 2003-2015 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#include <fstream> 21#include <locale> 22#include <cstdio> 23#include <testsuite_hooks.h> 24 25template <typename InternT, typename StateT = mbstate_t> 26class checksumcvt : public std::codecvt<InternT, char, StateT> 27{ 28 typedef std::codecvt<InternT, char, StateT> Base; 29 static const size_t width = sizeof(InternT) + 1; 30 31public: 32 typedef InternT intern_type; 33 typedef char extern_type; 34 35 explicit checksumcvt(size_t refs = 0) 36 : Base(refs) 37 { } 38 39protected: 40 virtual typename std::codecvt<InternT, char, StateT>::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 = reinterpret_cast<const char*>(from); 52 unsigned char checksum = 0; 53 54 for (size_t i = 0; i < sizeof(intern_type); ++i) 55 { 56 *to++ = p[i]; 57 checksum ^= static_cast<unsigned char>(p[i]); 58 } 59 60 *to++ = checksum; 61 ++from; 62 } 63 64 from_next = from; 65 to_next = to; 66 return from_next == from_end ? std::codecvt<InternT, char, StateT>::ok 67 : std::codecvt<InternT, char, StateT>::partial; 68 } 69 70 virtual typename std::codecvt<InternT, char, StateT>::result 71 do_unshift(StateT&, extern_type* to, 72 extern_type*, extern_type*& to_next) const 73 { 74 to_next = to; 75 return std::codecvt<InternT, char, StateT>::ok; 76 } 77 78 virtual typename std::codecvt<InternT, char, StateT>::result 79 do_in(StateT&, const extern_type* from, 80 const extern_type* from_end, const extern_type*& from_next, 81 intern_type* to, intern_type* to_end, 82 intern_type*& to_next) const 83 { 84 size_t len = std::min(static_cast<size_t>(to_end - to), 85 static_cast<size_t>(from_end - from) / width); 86 87 while (len) 88 { 89 const char* f = from; 90 intern_type tmp; 91 char* p = reinterpret_cast<char*>(&tmp); 92 unsigned char checksum = 0; 93 94 for (size_t i = 0; i < sizeof(intern_type); ++i) 95 { 96 p[i] = *f; 97 checksum ^= static_cast<unsigned char>(*f++); 98 } 99 100 if (*f++ != checksum) 101 break; 102 103 from = f; 104 *to++ = tmp; 105 len--; 106 } 107 108 from_next = from; 109 to_next = to; 110 return len ? std::codecvt<InternT, char, StateT>::error : 111 (from_next == from_end ? std::codecvt<InternT, char, StateT>::ok 112 : std::codecvt<InternT, char, StateT>::partial); 113 } 114 115 virtual int 116 do_encoding() const throw() 117 { return width; } 118 119 virtual int 120 do_length(StateT&, const extern_type* from, 121 const extern_type* end, size_t max) const 122 { 123 size_t len = std::min(max, static_cast<size_t>(end - from) / width); 124 125 int ret = 0; 126 while (len--) 127 { 128 unsigned char checksum = 0; 129 130 for (size_t i = 0; i < sizeof(intern_type); ++i) 131 { 132 checksum ^= static_cast<unsigned char>(*from++); 133 } 134 135 if (*from++ != checksum) 136 break; 137 138 ret++; 139 } 140 141 return ret; 142 } 143 144 virtual int 145 do_max_length() const throw() 146 { return width; } 147 148 virtual bool 149 do_always_noconv() const throw() 150 { return false; } 151}; 152 153// libstdc++/11544 (invalid byte sequence in file) 154void test02() 155{ 156 using namespace std; 157 bool test __attribute__((unused)) = true; 158 159 locale loc(locale::classic(), new checksumcvt<wchar_t>); 160 161 const char* name = "tmp_11544-2"; 162 163 FILE* f = fopen(name, "w"); 164 VERIFY( fwrite("aaaab", 1, 5, f) == 5 ); 165 fclose(f); 166 167 wifstream in; 168 in.imbue(loc); 169 in.open(name); 170 171 VERIFY( in.good() ); 172 in.get(); 173 VERIFY( !in.good() ); 174 VERIFY( in.bad() ); 175 VERIFY( !in.eof() ); 176 177 in.close(); 178} 179 180int main() 181{ 182 test02(); 183 return 0; 184} 185