// Copyright (C) 2010 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the // terms of the GNU General Public License as published by the // Free Software Foundation; either version 3, or (at your option) // any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License along // with this library; see the file COPYING3. If not see // . // 27.8.1.4 Overridden virtual functions #include #include #include class reverse_word_cvt : public std::codecvt { enum { wordsz = 6 }; struct state { char unconved[wordsz]; unsigned char cnt; }; result do_out(std::mbstate_t &ss, char const *ff, char const *fl, char const *&fn, char *tf, char *tl, char *&tn) const { fn = ff; tn = tf; state &s = reinterpret_cast(ss); if (s.cnt >= wordsz) return error; while (tn <= tl - sizeof s) { for (size_t into_state = std::min(wordsz - s.cnt, int(fl - fn)); into_state > 0; --into_state) s.unconved[wordsz - ++s.cnt] = *fn++; if (s.cnt != wordsz) break; char const *sr = reinterpret_cast(&s); tn = std::copy(sr, sr + sizeof s, tn); s = state(); } if (fn != fl) return partial; return ok; } result do_in(std::mbstate_t &ss, char const *ff, char const *fl, char const *&fn, char *tf, char *tl, char *&tn) const { fn = ff; tn = tf; state &s = reinterpret_cast(ss); if (s.cnt >= wordsz) return error; switch (s.cnt) do { case 0: if (tn == tl) break; std::copy(fn, fn + sizeof s, reinterpret_cast(&s)); default: for (size_t from_state = std::min(size_t(s.cnt), size_t(tl - tn)); from_state > 0; --from_state) *tn++ = s.unconved[--s.cnt]; } while (s.cnt == 0 && (fn += sizeof s) < fl); if (fn < fl || s.cnt != 0) return partial; return ok; } result do_unshift(std::mbstate_t &ss, char *tf, char *tl, char *&tn) const { tn = tf; state &s = reinterpret_cast(ss); if (s.cnt >= wordsz) return error; if (tn + sizeof s >= tl) return partial; char const *sr = reinterpret_cast(&s); tn = std::copy(sr, sr + sizeof s, tn); return ok; } int do_length(std::mbstate_t &ss, char const *ff, char const *fl, size_t tn) const { state &s = reinterpret_cast(ss); if (s.cnt >= wordsz) return error; int ret = 0; switch (s.cnt) do { case 0: if (tn == 0) break; std::copy(ff + ret, ff + ret + sizeof s, reinterpret_cast(&s)); default: size_t from_state = std::min(size_t(s.cnt), tn); tn -= from_state; s.cnt -= from_state; } while (s.cnt == 0 && ff + (ret += sizeof s) < fl); return ret; } int do_max_length() const throw() { return sizeof (state); } int do_encoding() const throw() { return -1; } bool do_always_noconv() const throw() { return false; } }; int main() { std::filebuf fb; fb.open("imbue_1.tst", std::ios::in|std::ios::out|std::ios::trunc); char const se[] = "encoded text", sne[] = "non-encoded text"; fb.sputn(sne, sizeof sne); std::locale l(std::locale(), new reverse_word_cvt); fb.pubimbue(l); std::cout << std::use_facet >(fb.getloc()) .max_length() << '\n'; fb.sputn(se, sizeof se); fb.pubimbue(std::locale()); fb.sputn(sne, sizeof sne); fb.pubseekoff(0, std::ios::beg); for (int i = 0; i < sizeof sne; ++i) fb.sbumpc(); char buf[5]; fb.pubimbue(l); fb.sgetn(buf, sizeof buf); std::cout.write( buf, sizeof buf ); std::streampos p = fb.pubseekoff(0, std::ios::cur); fb.pubimbue(std::locale()); fb.pubseekoff(0, std::ios::beg); fb.pubimbue(l); fb.pubseekpos(p); fb.sgetn(buf, sizeof buf); std::cout.write( buf, sizeof buf ); endl(std::cout); for (int i = 0; i < sizeof se - 10; ++i) fb.sbumpc(); fb.pubimbue(std::locale()); fb.sgetn(buf, sizeof buf); std::cout.write( buf, sizeof buf ); endl(std::cout); }