Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > std::streambuf::setp and std::streambuf::epptr()

Reply
Thread Tools

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

 
 
Christopher Pisz
Guest
Posts: n/a
 
      12-12-2007
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:base(),
std::streambuf:base()); 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:base() + 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.


 
Reply With Quote
 
 
 
 
hsmit.home@gmail.com
Guest
Posts: n/a
 
      12-12-2007
On Dec 12, 9:12 am, "Christopher Pisz" <(E-Mail Removed)> 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:base(),
> std::streambuf:base()); 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:base() + 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);
  }
};
 
Reply With Quote
 
 
 
 
James Kanze
Guest
Posts: n/a
 
      12-12-2007
On Dec 12, 9:12 am, "Christopher Pisz" <(E-Mail Removed)> 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:base(),
> std::streambuf:base()); 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:base() + 1?


That would provide a buffer of size 1.

--
James Kanze (GABI Software) email:(E-Mail Removed)
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
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
if and and vs if and,and titi VHDL 4 03-11-2007 05:23 AM



Advertisments