// 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);
}