std::streambuf::setp and std::streambuf::epptr()

Discussion in 'C++' started by Christopher Pisz, Dec 12, 2007.

  1. I am trying to empty and reset my internal buffer in my derived sync method.

    Am I correct in assuming I can call setp( std::streambuf::pbase(),
    std::streambuf::pbase()); to reset the internal buffer?

    Also, I am unsure whether the pointer returned by epptr() is supposed to
    point just beyond the end of the sequence or at the last element of the
    sequence? As such, should the second argument to my setp call be
    std::streambuf::pbase() + 1?

    Thanks. I've got a book on streams coming for Christmas by the way. Yay!
    References on the topic seem to be scarce, yet it is such a huge topic. I
    guess most people ignore it as much as they can.
     
    Christopher Pisz, Dec 12, 2007
    #1
    1. Advertising

  2. Christopher Pisz

    Guest

    On Dec 12, 9:12 am, "Christopher Pisz" <> wrote:
    > I am trying to empty and reset my internal buffer in my derived sync method.
    >
    > Am I correct in assuming I can call setp( std::streambuf::pbase(),
    > std::streambuf::pbase()); to reset the internal buffer?

    I think your assumption looks correct but shouldn't the 2nd argument
    be pbase() + buffer len?
    I need to brush up on the STL documentation before I can confirm this.

    >
    > Also, I am unsure whether the pointer returned by epptr() is supposed to
    > point just beyond the end of the sequence or at the last element of the
    > sequence? As such, should the second argument to my setp call be
    > std::streambuf::pbase() + 1?


    >
    > Thanks. I've got a book on streams coming for Christmas by the way. Yay!
    > References on the topic seem to be scarce, yet it is such a huge topic. I
    > guess most people ignore it as much as they can.

    Yes, I've read "C++ Standard Library, The: A Tutorial and Reference"
    and they did a reasonable job of explaing all of this. But I want
    more!

    In case your interested, this is what I managed to conjure up with the
    help of the above mentioned reference. It works for me, but is still
    under going testing and refinements. I use it as a base class for
    tcpip socket and serial comm communication (and encoding).

    Code:
    //--------------------------------------------------------------
    /**
      A generic buffered stream that can be used as the base class
      for hardware / network interfaces such as serial ports, tcpip
      sockets and any device that acts as a I/O stream.
    
      @ingroup io
      */
    class iobuffer : public std::streambuf {
    
      int                           mLock;
      char *                        mIBuf;
      char *                        mOBuf;
      std::streamsize               mBufSize;
    
    protected:
      //--------------------------------------------------------------
      /**
        Default constructor that provides an abstract base class,
        only inheriting classes may be instantiated.
      */
      iobuffer ()
      : mLock (0)
      , mIBuf(NULL)
      , mOBuf(NULL)
      {
        allocate(8192);
      }
    
      //--------------------------------------------------------------
      /** destructor */
      virtual ~iobuffer () {
        if (is_locked()) {
          std::cout << "what duh? what should I do now...wait...maybe." <<
    std::endl;
        }
        deallocate();
      }
    
    public:
      //--------------------------------------------------------------
      /**
        Returns the number of bytes that may be read from the device.
        If the device is not open or has been closed, a 0 will be
        returned. If a 0 is returned the caller should check whether
        this was due to an invalid device by using the is_open method,
        else the device's receive buffer is empty.
    
        @todo investigate whether or not to use showmanyc protected
    sstream
       */
      virtual std::streamsize       avail () = 0;
    
      //--------------------------------------------------------------
      /**
        The low-level command that sends the specified binary character
        sequence to the device. A EOF (-1) will be returned if a failure
        occurs, else the number of bytes successfully sent will be
        returned.
        */
      virtual int                   send (const char * s, size_t n) = 0;
    
      //--------------------------------------------------------------
      /**
        Attempts to receive a maximum number of n characters from the
        device, and copy them into the specified s buffer.
        */
      virtual int                   recv (char * s, size_t n) = 0;
    
      //--------------------------------------------------------------
      /**
       */
      bool                          is_locked () const {
        return (mLock != 0);
      }
    
      //--------------------------------------------------------------
      void                          lock () {
        mLock = 1;
      }
    
      //--------------------------------------------------------------
      void                          unlock () {
        mLock = 0;
      }
    
      //--------------------------------------------------------------
      void                          deallocate () {
        if (mIBuf) {
          delete[] mIBuf;
        }
        if (mOBuf) {
          delete[] mOBuf;
        }
        mIBuf = NULL;
        mOBuf = NULL;
        mBufSize = 0;
      }
    
      //--------------------------------------------------------------
      void                          allocate (size_t len) {
    
        deallocate();
    
        mBufSize = len;
        // allocate 2 extra characters to enable
        // null terminated unicode padding
        mIBuf = new char[mBufSize+2];
        mOBuf = new char[mBufSize+2];
    
        setg(mIBuf, mIBuf+mBufSize, mIBuf+mBufSize);
        setp(mOBuf, mOBuf+mBufSize);
        // TODO: throw memory exception in case of failure
      }
    
    protected:
      //--------------------------------------------------------------
      /** pure stream methods */
      //--------------------------------------------------------------
    
      //--------------------------------------------------------------
      int                           flush () {
    
        int n = static_cast<int>(pptr() - pbase());
    
        _send(mOBuf, n);
        pbump(-n);
    
        return n;
      }
    
      //--------------------------------------------------------------
      virtual int                   sync () {
    
        if (flush() == EOF) {
          return -1;
        }
        return 0;
      }
    
      //--------------------------------------------------------------
      virtual int_type              overflow (int_type c) {
    
        if (c != EOF) {
          *pptr() = c;
          pbump(1);
        }
        if (flush() == EOF) {
          return EOF;
        }
        return c;
      }
    
      //--------------------------------------------------------------
      /**
    
       */
      virtual int_type              underflow () {
    
        // is read position before end of buffer?
        if (gptr() < egptr()) {
          return *gptr();
        }
    
        std::streamsize n = avail();
        if (n == 0) {
          return EOF; // no more characters to read
        }
    
        if (n > mBufSize) {
          n = mBufSize; // if incoming data exceeds buffer size - throttle
    it.
        }
    
        std::streamsize len = _recv(mIBuf, n);
    
        if (len == -1) {
          return EOF; // ERROR
        }
        if (len == 0) {
          return EOF; // ERROR
        }
    
        setg(mIBuf, mIBuf, mIBuf+len);
        mIBuf[len] = 0; //null terminate (not really necessary)
    
    
        return ((unsigned char)(*gptr()));
      }
    
      //--------------------------------------------------------------
      /**
        Overrides the base xsgetn method, and enables faster through put
        when reading from the device.
       */
      virtual std::streamsize       xsgetn(char * s, std::streamsize n) {
    
        std::streamsize len = _recv(mIBuf, n);
    
        return len;
      }
    
    private:
      //--------------------------------------------------------------
      virtual int                   _send (const char * s, size_t n) {
        return send(s, n);
      }
    
      //--------------------------------------------------------------
      virtual int                   _recv (char * s, size_t n) {
        return recv(s, n);
      }
    };
    
    
     
    , Dec 12, 2007
    #2
    1. Advertising

  3. Christopher Pisz

    James Kanze Guest

    On Dec 12, 9:12 am, "Christopher Pisz" <> wrote:
    > I am trying to empty and reset my internal buffer in my
    > derived sync method.


    > Am I correct in assuming I can call setp( std::streambuf::pbase(),
    > std::streambuf::pbase()); to reset the internal buffer?


    It depends on what you want to do. If you simply want to clear
    the buffer, making sure that the next attempt to write will end
    up calling overflow() (where presumably, you'll reinitialize
    it), then setting both pointers to NULL is the simplest
    solution. If you want to initialize a new (empty) buffer, the
    first pointer should be the address of the buffer, and the
    second the address one past the end of the buffer.

    > Also, I am unsure whether the pointer returned by epptr() is
    > supposed to point just beyond the end of the sequence or at
    > the last element of the sequence?


    One past the end. epptr() - pbase() is the length of the
    buffer.

    > As such, should the second argument to my setp call be
    > std::streambuf::pbase() + 1?


    That would provide a buffer of size 1.

    --
    James Kanze (GABI Software) email:
    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
     
    James Kanze, Dec 12, 2007
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Peter Jansson
    Replies:
    1
    Views:
    512
    David Rubin
    Nov 8, 2004
  2. john

    SETP-07 Call for papers

    john, Feb 3, 2007, in forum: Java
    Replies:
    0
    Views:
    296
  3. Johannes Barop
    Replies:
    1
    Views:
    437
    JH Trauntvein
    Dec 29, 2005
  4. john
    Replies:
    0
    Views:
    342
  5. john
    Replies:
    0
    Views:
    293
Loading...

Share This Page