monotone-devel
[Top][All Lists]
Advanced

[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_ */




reply via email to

[Prev in Thread] Current Thread [Next in Thread]