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 <string> 23#include <iterator> 24#include <algorithm> 25#include <locale> 26#include <testsuite_hooks.h> 27 28template <typename InternT, typename StateT = mbstate_t> 29class checksumcvt : public std::codecvt<InternT, char, StateT> 30{ 31 typedef std::codecvt<InternT, char, StateT> Base; 32 static const size_t width = sizeof(InternT) + 1; 33 34public: 35 typedef InternT intern_type; 36 typedef char extern_type; 37 38 explicit checksumcvt(size_t refs = 0) 39 : Base(refs) 40 { } 41 42protected: 43 virtual typename std::codecvt<InternT, char, StateT>::result 44 do_out(StateT&, const intern_type* from, 45 const intern_type* from_end, const intern_type*& from_next, 46 extern_type* to, extern_type* to_end, 47 extern_type*& to_next) const 48 { 49 size_t len = std::min(static_cast<size_t>(from_end - from), 50 static_cast<size_t>(to_end - to) / width); 51 52 while (len--) 53 { 54 const char* p = reinterpret_cast<const char*>(from); 55 unsigned char checksum = 0; 56 57 for (size_t i = 0; i < sizeof(intern_type); ++i) 58 { 59 *to++ = p[i]; 60 checksum ^= static_cast<unsigned char>(p[i]); 61 } 62 63 *to++ = checksum; 64 ++from; 65 } 66 67 from_next = from; 68 to_next = to; 69 return from_next == from_end ? std::codecvt<InternT, char, StateT>::ok 70 : std::codecvt<InternT, char, StateT>::partial; 71 } 72 73 virtual typename std::codecvt<InternT, char, StateT>::result 74 do_unshift(StateT&, extern_type* to, 75 extern_type*, extern_type*& to_next) const 76 { 77 to_next = to; 78 return std::codecvt<InternT, char, StateT>::ok; 79 } 80 81 virtual typename std::codecvt<InternT, char, StateT>::result 82 do_in(StateT&, const extern_type* from, 83 const extern_type* from_end, const extern_type*& from_next, 84 intern_type* to, intern_type* to_end, 85 intern_type*& to_next) const 86 { 87 size_t len = std::min(static_cast<size_t>(to_end - to), 88 static_cast<size_t>(from_end - from) / width); 89 90 while (len) 91 { 92 const char* f = from; 93 intern_type tmp; 94 char* p = reinterpret_cast<char*>(&tmp); 95 unsigned char checksum = 0; 96 97 for (size_t i = 0; i < sizeof(intern_type); ++i) 98 { 99 p[i] = *f; 100 checksum ^= static_cast<unsigned char>(*f++); 101 } 102 103 if (*f++ != checksum) 104 break; 105 106 from = f; 107 *to++ = tmp; 108 len--; 109 } 110 111 from_next = from; 112 to_next = to; 113 return len ? std::codecvt<InternT, char, StateT>::error : 114 (from_next == from_end ? std::codecvt<InternT, char, StateT>::ok 115 : std::codecvt<InternT, char, StateT>::partial); 116 } 117 118 virtual int 119 do_encoding() const throw() 120 { 121 return width; 122 } 123 124 virtual int 125 do_length(StateT&, const extern_type* from, 126 const extern_type* end, size_t max) const 127 { 128 size_t len = std::min(max, static_cast<size_t>(end - from) / width); 129 130 int ret = 0; 131 while (len--) 132 { 133 unsigned char checksum = 0; 134 135 for (size_t i = 0; i < sizeof(intern_type); ++i) 136 { 137 checksum ^= static_cast<unsigned char>(*from++); 138 } 139 140 if (*from++ != checksum) 141 break; 142 143 ret++; 144 } 145 146 return ret; 147 } 148 149 virtual int 150 do_max_length() const throw() 151 { 152 return width; 153 } 154 155 virtual bool 156 do_always_noconv() const throw() 157 { 158 return false; 159 } 160}; 161 162void test01() 163{ 164 using namespace std; 165 bool test __attribute__((unused)) = true; 166 167 locale loc; 168 loc = locale(loc, new checksumcvt<wchar_t>); 169 170 wfilebuf fbuf1; 171 fbuf1.pubimbue(loc); 172 fbuf1.open("tmp_9178", ios_base::out | ios_base::trunc); 173 174 string tmpstr = "abcdefghijklmnopqrstuvwxyz0123456789 \t\n"; 175 176 wifstream stream; 177 wstring str1; 178 179 while (str1.length() < 20000) 180 { 181 transform(tmpstr.begin(), tmpstr.end(), 182 back_inserter(str1), 183 bind1st(std::mem_fun(&std::wios::widen), &stream)); 184 } 185 186 fbuf1.sputn(str1.data(), str1.size()); 187 fbuf1.close(); 188 189 wfilebuf fbuf2; 190 fbuf2.pubimbue(loc); 191 fbuf2.open("tmp_9178", std::ios_base::in); 192 193 wstring str2; 194 copy(istreambuf_iterator<wchar_t>(&fbuf2), 195 istreambuf_iterator<wchar_t>(), 196 back_inserter(str2)); 197 198 VERIFY( str1 == str2 ); 199} 200 201int main() 202{ 203 test01(); 204 return 0; 205} 206