[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Monotone-devel] Monotone ID shortener
From: |
Nathan Myers |
Subject: |
Re: [Monotone-devel] Monotone ID shortener |
Date: |
Fri, 30 Apr 2004 11:31:17 -0700 |
User-agent: |
Mutt/1.3.28i |
On Fri, Apr 30, 2004 at 05:40:22PM +0200, Christof Petig wrote:
> monoshort "monotone --db monotone.db" > short.sed
>
> PS: No, _I_ did _not_ design the semantics of underflow/uflow, I only
> struggled to implement them.
Probably you would do better to extract the file descriptor from the
FILE returned by popen, and then attach a buffering streambuf to it.
(It probably would be little more than two orders of magnitude faster.)
What you really want, most likely, is Jonathan Wakely's streambuf
equivalent to popen that attaches streambufs instead of FILE*s. In
the meantime, here are some fd streambufs and streams.
Nathan Myers
address@hidden
#ifndef _FDBUF_H_
#define _FDBUF_H_ 1
#include "stdio.h"
#include "unistd.h"
# include <streambuf>
# include <istream>
# include <ostream>
// For reference see Josuttis, "The C++ Standard Library", 13.13.3.
// Note the casts to unsigned char, and the explicit constructors.
// Josuttis erroneously omits them.
class FdOutBuf : public std::streambuf
{
public:
explicit FdOutBuf(int d)
: fd(d)
{ this->setp(this->buf, this->buf+(size-1)); }
~FdOutBuf() { this->sync(); }
protected:
virtual int overflow(int ic)
{
if (ic != EOF) {
// Double check that there is room for a character, otherwise
// assume a previous I/O output failed, in which case just
// returning a failure now is appropriate.
if (pptr() >= &buf[size])
return EOF;
*this->pptr() = char(ic);
this->pbump(1);
}
if (sync() < 0)
return EOF;
return ic;
}
virtual int sync()
{
char const* p = this->pbase();
int n = this->pptr() - p;
while (n) {
int done = ::write(fd, p, n);
if (done < 0)
return -1;
n -= done;
p += done;
}
this->pbump(-(p - this->pbase()));
return 0;
}
private:
enum { size = 1 << 13 } ;
int fd;
char buf[size];
};
class FdOStream : public std::ostream
{
public:
explicit FdOStream(int fd) : std::ostream(&buf), buf(fd) {}
private:
FdOutBuf buf;
};
class FdInBuf : public std::streambuf
{
public:
explicit FdInBuf(int d)
: fd(d) { this->setg(this->buf+size, this->buf+size, this->buf+size); }
virtual int underflow()
{
if (this->gptr() < this->egptr()) {
return (unsigned char) *this->gptr();
}
bool pb = (this->gptr() - this->eback()) != 0;
if (pb) this->buf[0] = this->gptr()[-1];
int got = ::read(this->fd, this->buf+1, this->size-1);
if (got <= 0) {
return EOF;
}
this->setg(buf+(1-pb), buf+1, buf+1+got);
return (unsigned char) *this->gptr();
}
private:
enum { size = 1 << 13 } ;
int fd;
char buf[size];
};
class FdIStream : public std::istream
{
public:
explicit FdIStream(int fd) : std::istream(&buf), buf(fd) {}
private:
FdInBuf buf;
};
#endif /* _FDBUF_H_ */