473,386 Members | 1,798 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

Problem with streambuf

Hi there.

I'm writing a program that uses the Telnet protocol over TCP/IP
sockets. Of course, that has no bearing here, so I'll rephrase that
in Standard C++ :)

In essense, I'm trying to manipulate a data stream by using a custom
streambuf, so that I can access this as "just another iostream".
Alas, this data stream has a couple of "interesting" properties:

1) It is non-blocking. There is a chance that, when reading from this
stream, there will be a flag of "no data". This doesn't mean "there
will not ever be any data", just "nothing right now, check back
later".

2) 0 is a meaningful value.

Combined, I am unsure of how to proceed. Sending negative numbers
seems not to work: Returning -1 in the case of no data sets fail bits
and looks identical to EOF (indeed, I believe it is the value returned
in the case of an EOF, at least on my platform). Returning -2 is
detectable when reading from the stream as strm.getc(), but tends
towards garbage when using the >> operator.

In short, does anybody know how to communicate "no data" from
streambuf to stream, or would I have to write a custom stream too?

Thanks,

Matt Chaplain

--
To reply by e-mail, send to something -other- than nospam@.
Jul 19 '05 #1
4 3112

"Matt Chaplain" <no****@kastagaar.com> wrote in message
news:5e**************************@posting.google.c om...
Hi there.

I'm writing a program that uses the Telnet protocol over TCP/IP
sockets. Of course, that has no bearing here, so I'll rephrase that
in Standard C++ :)

In essense, I'm trying to manipulate a data stream by using a custom
streambuf, so that I can access this as "just another iostream".
Alas, this data stream has a couple of "interesting" properties:

1) It is non-blocking. There is a chance that, when reading from this
stream, there will be a flag of "no data". This doesn't mean "there
will not ever be any data", just "nothing right now, check back
later".

2) 0 is a meaningful value.

Combined, I am unsure of how to proceed. Sending negative numbers
seems not to work: Returning -1 in the case of no data sets fail bits
and looks identical to EOF (indeed, I believe it is the value returned
in the case of an EOF, at least on my platform). Returning -2 is
detectable when reading from the stream as strm.getc(), but tends
towards garbage when using the >> operator.

In short, does anybody know how to communicate "no data" from
streambuf to stream, or would I have to write a custom stream too?

Thanks,

Matt Chaplain


The mechanism to use nonblocking input from a stream is to use the readsome
method.

To implement the readsome method correctly you must implement showmanyc on
your streambuf.

None of this means that a user who does uses one of the blocking input
methods (e.g. operator>>, get or read) will get non-blocking input. Even
peek is a blocking input method. To get non-blocking input you must use
readsome.

john
Jul 19 '05 #2
On 30 Jul 2003 03:33:09 -0700, no****@kastagaar.com (Matt Chaplain)
wrote:
Hi there.

I'm writing a program that uses the Telnet protocol over TCP/IP
sockets. Of course, that has no bearing here, so I'll rephrase that
in Standard C++ :)

In essense, I'm trying to manipulate a data stream by using a custom
streambuf, so that I can access this as "just another iostream".
Alas, this data stream has a couple of "interesting" properties:

1) It is non-blocking. There is a chance that, when reading from this
stream, there will be a flag of "no data". This doesn't mean "there
will not ever be any data", just "nothing right now, check back
later".
This is still EOF - it just means that you can clear EOF and try again
later, if you so choose.
2) 0 is a meaningful value.
This is true of all standard streams.

Combined, I am unsure of how to proceed. Sending negative numbers
seems not to work: Returning -1 in the case of no data sets fail bits
and looks identical to EOF (indeed, I believe it is the value returned
in the case of an EOF, at least on my platform). Returning -2 is
detectable when reading from the stream as strm.getc(), but tends
towards garbage when using the >> operator.
Returning traits_type::eof() is the correct thing to do if you can't
get any more data without blocking, and you don't want to block.
However, to make sure you don't lose bytes, clients will have to stick
to the istream::read function - operator>> functions may end up
throwing away data if EOF is reached in the middle of the operation.

It would be nice if operator>> functions at least attempted to return
a stream to its former state if the operation failed (using putback),
but implementations don't seem to bother since the interfaces aren't
set up to do it easily.

You could make sure that your streambuf can handle a reasonable number
of putback calls, and that your own operator>> functions put back any
characters they had read if they failed, and then the lost character
problem wouldn't occur.

The final solution is to ensure that the stream will return enough
characters to complete any input operation (e.g. only whole things
will be written, and can thus be read back without blocking), in which
case you'll only lose characters if something has gone "properly"
wrong.
In short, does anybody know how to communicate "no data" from
streambuf to stream, or would I have to write a custom stream too?


Just return EOF, and remind users that they have to clear the stream
if they want more data.

Tom
Jul 19 '05 #3
no****@kastagaar.com (Matt Chaplain) wrote:
2) 0 is a meaningful value.
You mean the character '0' is a meaningful value? Sure, this is always the
case. This is the reason why there is a distinction between "char_type"
which is used to represent all meaningful values and "int_type" which is
used to represent all meaningful value plus one value indicating that there
is no such value which is called "EOF".

Note that for some character types, the char_type and the int_type are
actually identical: for example, for 'wchar_t' on 32 bit systems where
'wchar_t' has 32 bits (eg. when using gcc), the corresponding int_type is
also 'wchar_t': 32 bits are sufficient to encode all characters (eg. all
Unicode charactesr) and still have a distinct value for EOF.
Combined, I am unsure of how to proceed. Sending negative numbers
seems not to work: Returning -1 in the case of no data sets fail bits
and looks identical to EOF (indeed, I believe it is the value returned
in the case of an EOF, at least on my platform).
-1 is the typical choice for EOF but it is not a requirement. You should
use a symbolic name anyway.
Returning -2 is
detectable when reading from the stream as strm.getc(), but tends
towards garbage when using the >> operator.
Well, the -2 should be used as a normal character when returned from
functions like 'std::streambuf::sgetc()': the IOStream classes form two
groups of values returned from 'sgetc()' and family:

- normal characters which are identified by being distinct from EOF
- EOF or, more precisely, "traits_type::eof()"

Thus, to indicate an expected problem (like "no more data [yet]"), you would
simply return EOF: this is what these functions use to detect failures.
.... and it results in a failure to attempt reading a character when there is
none: there is different processing depending on whether there were
characters or not. Since the IOStream functions set error flags when EOF is
returned, you should simply 'clear()' these error flags.
In short, does anybody know how to communicate "no data" from
streambuf to stream, or would I have to write a custom stream too?


I would use EOF to signal "no data" or, as I would formulated it, "[current]
end of file". On streams which might receive new data in the future, I would
then just clear the error flags: since I need to do different processing
in the two cases (there was a character or there was none) there is no
problem anyway. The only interesting issue is how to signal "real" end of
file as is indicated eg. on POSIX systems by a -1 return from 'read()' rather
than a '0' return in case there is currently no data. A possible approach is
to throw an exception in this case from 'underflow()' or whatever functions
you have overridden and explicitly check for 'badbit' in the streams.

Personally, I would also override 'showmanyc()' to check whether there is a
character in the buffer or if there is a character available via 'read()'.
This way, normal processing could look something like this:

if (stream.in_avail())
...

rather than 'clear()'ing the stream after each failed attempted: a read
attempt is only made when it is known that there is at least a character.
However, if the a priori check is not made, reading a character will, of
course, still fail. That is, a client knowing that the stream is non-blocking
and may receive characters later even if currently none are available will
take advantage of this. However, any other approach also has to an impact on
the client side be it by 'clear()'ing the state flags, by testing for special
value, etc.
--
<mailto:di***********@yahoo.com> <http://www.dietmar-kuehl.de/>
Phaidros eaSE - Easy Software Engineering: <http://www.phaidros.com/>
Jul 19 '05 #4
di***********@yahoo.com (Dietmar Kuehl) wrote in message news:<5b**************************@posting.google. com>...
no****@kastagaar.com (Matt Chaplain) wrote:
2) 0 is a meaningful value.
You mean the character '0' is a meaningful value? Sure, this is always the
case. This is the reason why there is a distinction between "char_type"
which is used to represent all meaningful values and "int_type" which is
used to represent all meaningful value plus one value indicating that there
is no such value which is called "EOF".


Indeed, but I just threw this out to pre-empt the otherwise possible
response of returning '0' in case of "no data" which would, in
essence, create an empty string.
Note that for some character types, the char_type and the int_type are
actually identical: for example, for 'wchar_t' on 32 bit systems where
'wchar_t' has 32 bits (eg. when using gcc), the corresponding int_type is
also 'wchar_t': 32 bits are sufficient to encode all characters (eg. all
Unicode charactesr) and still have a distinct value for EOF.
I'll admit I hadn't given the whole portability issue much thought,
what with using common, but ultimately platform-dependent code behind
this streambuf, and I don't think it's even possible to use wchar_t
for the purpose I'm putting it to, though it would be an interesting
ability. Feel free to correct me.
Returning -2 is
detectable when reading from the stream as strm.getc(), but tends
towards garbage when using the >> operator.


Well, the -2 should be used as a normal character when returned from
functions like 'std::streambuf::sgetc()': the IOStream classes form two
groups of values returned from 'sgetc()' and family:

- normal characters which are identified by being distinct from EOF
- EOF or, more precisely, "traits_type::eof()"

Thus, to indicate an expected problem (like "no more data [yet]"), you would
simply return EOF: this is what these functions use to detect failures.


So the nitty-gritty of it is: sgetc returns one value from one of two
sets: {all characters} and {EOF}. There is no way of signalling
anything else.
I would use EOF to signal "no data" or, as I would formulated it, "[current]
end of file". On streams which might receive new data in the future, I would
then just clear the error flags: since I need to do different processing
in the two cases (there was a character or there was none) there is no
problem anyway. The only interesting issue is how to signal "real" end of
file
Unfortunately, I missed off a couple of requirements: that "no current
data" (Fake EOF) must be distinguishable from "no data ever" (Real
EOF), and that the user should not need very much (if any) extraneous
code to handle the stream. In the ideal case, no-data should be
returned as an empty string, but this seems not to be possible.
A possible approach is to throw an exception in this case from 'underflow()'
or whatever functions you have overridden and explicitly check for 'badbit'
in the streams.
It is unlikely that having no data is an exceptional condition. In
fact, it's more likely the expected norm for the purpose I'm going to
put it to.
Personally, I would also override 'showmanyc()' to check whether there is a
character in the buffer or if there is a character available via 'read()'.
This way, normal processing could look something like this:

if (stream.in_avail())
...


I'd never heard of showmanyc before posting my question, since I tend
to look in Josuttis first before Stroustrup, where it's completely
overlooked.

Anyway, this seems like the best solution: to allow the cases that
require the non-blocking to explicitly check for it and guard against
the blocking calls, with a minimum of effort.

Thanks everyone who replied.

Matt Chaplain
--
To reply by e-mail, use something -other- than nospam@.
Jul 19 '05 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: Viktor Lundström | last post by:
Hi! I was planning to wrap a socket inside an iostream, to achieve something like this: TCPSocket s(..); s << "Hello!" << endl; Information on the web seems to be a bit scarce on how to do...
9
by: Fred Ma | last post by:
Hello, I posted previously under the thread: How to break this up into streambuf/ostream I've asked our library to get "C++ IOStreams and Locales..." by A. Langer et al. Meantime, I've...
9
by: Marcin Kalicinski | last post by:
Hi, I have a set of C-like functions for file access (like fopen, fwrite, fread, fseek etc.). But I want to access the files using C++ stream, not these functions. What I probably need to do is...
1
by: Johannes Barop | last post by:
Hello, i try to implement a streambuffer. I overwrote streambuf::overflow() and streambuf::xsputn(). Both are protected and virtual (http://www.cplusplus.com/ref/iostream/streambuf/). But...
7
by: smith4894 | last post by:
Hello all, I'm working on writing my own streambuf classes (to use in my custom ostream/isteam classes that will handle reading/writing data to a mmap'd file). When reading from the mmap...
0
by: tryptik | last post by:
All- I have been looking at all the info I can find on deriving streambuf objects, but I need some advice. I wish to derive a custom streambuf that filters out c++ style comments. I have...
4
by: SpreadTooThin | last post by:
My compiler seems unhappy with int_type The method declaration is: int_type dbgBuf::overflow(int_type ch) { #ifdef FF_DEBUG if (traits_type::not_eof(ch)) {
4
by: rakesh.usenet | last post by:
For a particular application of mine - I need a simulation of byte array output stream. * write data onto a stream * getback the contiguous content as an array later for network transport. ...
10
by: hsmit.home | last post by:
Hi everyone, I'm having some difficulty with the following piece of code. I have stripped it to it's bare minimum to demonstrate the problem at hand. Compiler: MS Visual C++ 2005 Express...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.