C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

problem with deriving from basic_filebuf and overflow

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Guest






PostPosted: Thu Feb 02, 2006 5:00 pm    Post subject: problem with deriving from basic_filebuf and overflow Reply with quote



template <class charT, class traits = std::char_traits<charT> >
class log_buf: public basic_filebuf<charT, traits>
{
public:

// All derived streams should have these types defined,
// even though they are inherited from the base,
// to make referring to them easy.
typedef charT char_type;
typedef traits traits_type;
typedef typename traits_type::int_type int_type;
typedef typename traits_type::off_type off_type;
typedef typename traits_type::pos_type pos_type;

log_buf(const char* fname, unsigned int lines):
basic_filebuf<charT, traits>()
{
cur_lines = max_lines = lines;
name = fname;
}

~log_buf()
{
pubsync();
close();
}

protected:
/*virtual*/
int_type overflow (int_type c = traits_type::eof ())
{
int_type ret = basic_filebuf<charT, traits>::overflow(c);
if('\n' == c && 0 == --cur_lines)
{
archive();
cur_lines = max_lines;
}

return ret;
}

private:
string name;
int_type max_lines, cur_lines;

void archive()
{
// close the open file, and rename it, then reopen the file
if(is_open())
{
pubsync();
close();

// rename silently handles the case where the file
named by _archive already exists
stringstream arch;
arch << name << ".bak";

if( 0 != rename(name.c_str(), arch.str().c_str()) )
perror("Failed to rename file");
else
basic_filebuf<charT, traits>::open( name.c_str(),
ios_base::out|ios_base::trunc);
}
}

};


template <class charT, class traits = std::char_traits<charT> >
class logstream: public basic_ostream<charT, traits>
{
log_buf<charT, traits> buf;

public:
typedef charT char_type;
typedef traits traits_type;
typedef typename traits_type::int_type int_type;
typedef typename traits_type::off_type off_type;
typedef typename traits_type::pos_type pos_type;

logstream(const char* fname, int_type lines):
basic_ostream<charT, traits>(&buf), buf(fname, lines)
{
this->init (&buf);
buf.open(fname, ios_base::out|ios_base::trunc);
if(!buf.is_open())
{
this->setstate (std::ios_base::failbit);
}
}

log_buf<charT, traits> *rdbuf () const
{
return (log_buf<charT, traits>*)&buf;
}
};



int main(int argc, char* argv[])
{
logstream<char> out(argv[1], atoi(argv[2]));

for(int i = atoi(argv[2])*3; i>0; i--)
{
out << "line " << i << '\n';
}

}

why is the call to buf.open failing ? And if it fails, how is the file
being created and written to, yet overflow is not called


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
kanze
Guest





PostPosted: Fri Feb 03, 2006 1:00 pm    Post subject: Re: problem with deriving from basic_filebuf and overflow Reply with quote



jack (AT) yankeeboysoftware (DOT) com wrote:
Quote:
template <class charT, class traits = std::char_traits<charT
class log_buf: public basic_filebuf<charT, traits
{

[no function open defined, so inherits open from filebuf...]
[function overflow defined, overrides the one in filebuf...]

Quote:
};

template <class charT, class traits = std::char_traits<charT
class logstream: public basic_ostream<charT, traits
{
log_buf<charT, traits> buf;
public:
typedef charT char_type;
typedef traits traits_type;
typedef typename traits_type::int_type int_type;
typedef typename traits_type::off_type off_type;
typedef typename traits_type::pos_type pos_type;

logstream(const char* fname, int_type lines):
basic_ostream<charT, traits>(&buf), buf(fname, lines)
{
this->init (&buf);
buf.open(fname, ios_base::out|ios_base::trunc);
if(!buf.is_open())
{
this->setstate (std::ios_base::failbit);
}
}

log_buf<charT, traits> *rdbuf () const
{
return (log_buf<charT, traits>*)&buf;
}
};

int main(int argc, char* argv[])
{
logstream<char> out(argv[1], atoi(argv[2]));

for(int i = atoi(argv[2])*3; i>0; i--)
{
out << "line " << i << '\n';
}
}

why is the call to buf.open failing ?

Is it? Where do you test it?

Quote:
And if it fails, how is the file being created and written to,
yet overflow is not called

If the file is being created, then open is not failing.

Physical writes to the file can occur in several functions: in
my implementations of streambuf's, the only physical writes are
in sync -- overflow *AND* close *AND* the destructor all call
this function. In the case of a filebuf, it's also possible
that xsputn call sync as well.

If output is buffered (and it certainly should be in filebuf),
the "standard" procedure is for the first call to overflow to
set up the buffer, but I'm using "standard" in the sense of
"generally accepted" here; there is nothing in the language
standard which says that an implementation must do it this way.

IMHO, this is the most logical implementation, but the standard
allows a lot of leeway. An implementation can set up buffering
in the constructor, for example, rather than in the first call
to overflow -- in this case, overflow will not be called until
the buffer is full (and if you don't fill the buffer before
calling close, it may never be filled). Historically, for I
don't know what reason, some implementations did the physical
write in overflow, calling overflow(EOF) from sync and the other
places where I would call sync. And of course, for performance
reasons, an implementation of filebuf will probably physically
write in some cases in xsputn.

For such reasons, it is generally a bad idea to derive from a
concrete streambuf -- deriving directly from streambuf, and
using a concrete streambuf in your implementation, is a much
better idea. (The technique is related to that of a filtering
streambuf; about the only difference is in a classical filtering
streambuf, it is the user who provides the final target, and
here, you will probably hard wire it into your implementation.)

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Guest






PostPosted: Sat Feb 04, 2006 5:01 am    Post subject: Re: problem with deriving from basic_filebuf and overflow Reply with quote



Sorry, this is essentially a duplicate posting, I thought my original
had been lost through an operator (that's me!) error.

Moderator, you are free to remove, or whatever you do with this.

Kanze, you are already replying to my other posting. Thanks. I have
reponded to your reply, but I can't see it on the history of the
posting


kanze wrote:
Quote:
jack (AT) yankeeboysoftware (DOT) com wrote:
template <class charT, class traits = std::char_traits<charT
class log_buf: public basic_filebuf<charT, traits
{

[no function open defined, so inherits open from filebuf...]
[function overflow defined, overrides the one in filebuf...]

};

template <class charT, class traits = std::char_traits<charT
class logstream: public basic_ostream<charT, traits
{
log_buf<charT, traits> buf;
public:
typedef charT char_type;
typedef traits traits_type;
typedef typename traits_type::int_type int_type;
typedef typename traits_type::off_type off_type;
typedef typename traits_type::pos_type pos_type;

logstream(const char* fname, int_type lines):
basic_ostream<charT, traits>(&buf), buf(fname, lines)
{
this->init (&buf);
buf.open(fname, ios_base::out|ios_base::trunc);
if(!buf.is_open())
{
this->setstate (std::ios_base::failbit);
}
}

log_buf<charT, traits> *rdbuf () const
{
return (log_buf<charT, traits>*)&buf;
}
};

int main(int argc, char* argv[])
{
logstream<char> out(argv[1], atoi(argv[2]));

for(int i = atoi(argv[2])*3; i>0; i--)
{
out << "line " << i << '\n';
}
}

why is the call to buf.open failing ?

Is it? Where do you test it?

And if it fails, how is the file being created and written to,
yet overflow is not called

If the file is being created, then open is not failing.

Physical writes to the file can occur in several functions: in
my implementations of streambuf's, the only physical writes are
in sync -- overflow *AND* close *AND* the destructor all call
this function. In the case of a filebuf, it's also possible
that xsputn call sync as well.

If output is buffered (and it certainly should be in filebuf),
the "standard" procedure is for the first call to overflow to
set up the buffer, but I'm using "standard" in the sense of
"generally accepted" here; there is nothing in the language
standard which says that an implementation must do it this way.

IMHO, this is the most logical implementation, but the standard
allows a lot of leeway. An implementation can set up buffering
in the constructor, for example, rather than in the first call
to overflow -- in this case, overflow will not be called until
the buffer is full (and if you don't fill the buffer before
calling close, it may never be filled). Historically, for I
don't know what reason, some implementations did the physical
write in overflow, calling overflow(EOF) from sync and the other
places where I would call sync. And of course, for performance
reasons, an implementation of filebuf will probably physically
write in some cases in xsputn.

For such reasons, it is generally a bad idea to derive from a
concrete streambuf -- deriving directly from streambuf, and
using a concrete streambuf in your implementation, is a much
better idea. (The technique is related to that of a filtering
streambuf; about the only difference is in a classical filtering
streambuf, it is the user who provides the final target, and
here, you will probably hard wire it into your implementation.)

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.