473,511 Members | 15,503 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Tracking information in input stream

I would like to make a stream or streambuf that tracks the number of
lines that have been read and stuff like that (so, for example, when I
get an error message, I can ask the stream for the line number and put
it in error messages. I tried to create a streambuf class that held an
instance of another streambuf (through parameterized inheritance) and
would ferry calls from the one to the other, tracking data as it was
read, but I wasn't able to get a hook that found where the data gets
passed to the calling application.

Has this problem already been solved? Is there a place I can look for a
ready-made solution?

Anyway, thanks for reading.

Adam H. Peterson
Jul 22 '05 #1
15 2199
"Adam H. Peterson" <ah**@email.byu.edu> wrote in message
news:cp***********@acs2.byu.edu...
I would like to make a stream or streambuf that tracks the number of
lines that have been read
You don't need to create your own stream or
stream buffer type to do this.

Just count the newsline characters when you read.
and stuff like that

"stuff like that" is such a vague phrase, I won't even
try to address it.
(so, for example, when I
get an error message, I can ask the stream for the line number and put
it in error messages.
Output the value of a counter which you increment when
encountering a newline character.
I tried to create a streambuf class that held an
instance of another streambuf (through parameterized inheritance) and
would ferry calls from the one to the other, tracking data as it was
read, but I wasn't able to get a hook that found where the data gets
passed to the calling application.
I think you're making things far more complex than necessary.

Has this problem already been solved? Is there a place I can look for a
ready-made solution?


Just do your i/o in a loop (typical way to do it anyway).
Exactly how you count newlines depends upon the functions
you use for your i/o. E.g. if you use cin.get(), check its
return value for '\n'. If you use e.g. 'std::getline', when
it returns, you know you've either encountered a newline, or
EOF (or an error occurred). You can sort out what happened
with e.g. 'eof()' and 'fail()'

-Mike
Jul 22 '05 #2
Mike Wahler wrote:
"Adam H. Peterson" <ah**@email.byu.edu> wrote in message
news:cp***********@acs2.byu.edu...
I would like to make a stream or streambuf that tracks the number of
lines that have been read

You don't need to create your own stream or
stream buffer type to do this.

Just count the newsline characters when you read.


This isn't really useful to me, though. If I have code like:

void f(istream &i) {
Object o;
i >> o;
}

I don't really want to poke around inside Object's stream extraction
operator, and I may be unable to. It's pretty common to have opaque I/O
routines that read and write objects or data structures of various
types. Often I can't instrument them, and even if I can, it usually
results in pretty messy looking code when compared with the original.
So I don't always have the option of keeping track of stuff as I read it
--- that is, unless I can get the stream to do it for me.
I tried to create a streambuf class that held an
instance of another streambuf (through parameterized inheritance) and
would ferry calls from the one to the other, tracking data as it was
read, but I wasn't able to get a hook that found where the data gets
passed to the calling application.

I think you're making things far more complex than necessary.


Possible. If I am, I would be grateful to know a simpler solution. (I
mean simple to code, rather than simple to explain.)

Has this problem already been solved? Is there a place I can look for a
ready-made solution?

Just do your i/o in a loop (typical way to do it anyway).
Exactly how you count newlines depends upon the functions
you use for your i/o. E.g. if you use cin.get(), check its
return value for '\n'. If you use e.g. 'std::getline', when
it returns, you know you've either encountered a newline, or
EOF (or an error occurred). You can sort out what happened
with e.g. 'eof()' and 'fail()'


Well, that's fine if I'm reading primitive values like characters or
lines. But even reading integers using >> will get me into trouble
because it will consume whitespace without an opportunity for me to
inspect it. And I'm thinking in general of the read-opaque-object
situation.

Instrumenting all the I/O routines I use reduces their encapsulation and
makes them harder to read, and I believe it would be error prone. If
the stream object can be made to track that information for me
internally, it would (I believe) just work.
Jul 22 '05 #3
Adam H. Peterson wrote:
I would like to make a stream or streambuf that tracks the number of
lines that have been read and stuff like that (so, for example, when I
get an error message, I can ask the stream for the line number and put
it in error messages. Has this problem already been solved? Is there a place I can look
for a ready-made solution?
The Boost Iostreams library, which will be included with the next release of
Boost (1.33), makes it easy to attach chains of filters to existing streams and
stream buffers. These filters can modify data, or simply observe it, as in your
case. I'm planning to add a filter which counts newlines, but haven't done so
yet.

Here's a simple filter for counting lines of input (untested):

#include <boost/iostreams/concepts.hpp> // input_filter
#include <boost/iostreams/operations.hpp> // get

using namespace std;
using namespace boost::io;

class line_counter : public input_filter {
public:
line_counter() : lines_(0) { }
int lines() const { return lines; }

template<typename Source>
int get(Source& src)
{
// Pass characters through unchanged.
int c = boost::io::get(src);
if (c == '\n')
++lines_;
return c;
}
private:
int lines_;
};

(This is just an illustration; the official version will be more efficient.) It
could be used as follows:

#include <iostream>
#include <boost/ref.hpp>
#include <boost/iostreams/filtering_istream.hpp>

using namespace std;
using namespace boost::io;

int main()
{
line_counter counter;
filtering_istream in;
in.push(boost::ref(counter)); // Push a reference to the counter
in.push(cin);

// Read from 'in' instead of 'cin'. counter will count the lines.
...

std::cout << "lines read from std::cin = " << counter.lines() << "\n";
}

It's also not fairly easy to write a class extending filtering_istream which
keeps track of the line count automatically.

The most recent version of the library is here:

http://home.comcast.net/~jturkanis/iostreams/

I plan to update it soon.
Adam H. Peterson


Best Regards,
Jonathan
Jul 22 '05 #4
Jonathan Turkanis wrote:
It's also not fairly easy to write a class extending


I'm pretty sure I meant to say "It's also failry easy" ...

Jonathan
Jul 22 '05 #5
Great.

I love Boost and use it all the time, so I'll surely look into it.

Are there any facilities in Boost 1.32 that I might be able to use to
this effect?

And/or do you have a good guess as to when the next Boost will be out?

Thanks for the response,
Adam H. Peterson
Jul 22 '05 #6
Adam H. Peterson wrote:
Great.

I love Boost and use it all the time, so I'll surely look into it.

Are there any facilities in Boost 1.32 that I might be able to use to
this effect?
I'm afraid not.
And/or do you have a good guess as to when the next Boost will be out?
As far as I know 1.33 hasn't been scheduled. Since 1.32 was just released, it's
sure to be a few months off.

Nearly 10 months elapsed between release 1.31 and 1.32, but this was unusual.
I'm hoping the next release will be in three or four months.
Thanks for the response,
Adam H. Peterson


Jonathan
Jul 22 '05 #7
"Adam H. Peterson" <ah**@email.byu.edu> wrote in message
news:cp***********@acs2.byu.edu...

Instrumenting all the I/O routines I use reduces their encapsulation and
makes them harder to read, and I believe it would be error prone. If
the stream object can be made to track that information for me
internally, it would (I believe) just work.


Now that you've elaborated upon what you want, I see
my advice is probably not applicable. See Jonathon T.'s reply.

-Mike
Jul 22 '05 #8
Adam H. Peterson wrote:
Great.

I love Boost and use it all the time, so I'll surely look into it.

Are there any facilities in Boost 1.32 that I might be able to use to
this effect?

And/or do you have a good guess as to when the next Boost will be out?


I'm succefully using Jonathan's IOStream library with boost 1.32 now (and
have used it with 1.31 also). It's just a matter of copying to the
appropriate directories.

Jeff
Jul 22 '05 #9
Jeff Flinn wrote:
I'm succefully using Jonathan's IOStream library with boost 1.32 now (and
have used it with 1.31 also). It's just a matter of copying to the
appropriate directories.


My copy of boost is installed through RPM and I'd rather not mess with
the package management system. Can I use the library without installing
it in the same directory tree as boost?
Jul 22 '05 #10
Adam Peterson wrote:
Jeff Flinn wrote:
I'm succefully using Jonathan's IOStream library with boost 1.32 now
(and have used it with 1.31 also). It's just a matter of copying to
the appropriate directories.
My copy of boost is installed through RPM and I'd rather not mess with


I've no idea what RPM is.
the package management system. Can I use the library without
installing it in the same directory tree as boost?


Someone with more boost.build knowledge would have to answer that.

Sorry, Jeff
Jul 22 '05 #11
Adam Peterson wrote:
Jeff Flinn wrote:
I'm succefully using Jonathan's IOStream library with boost 1.32 now
(and have used it with 1.31 also). It's just a matter of copying to
the appropriate directories.


My copy of boost is installed through RPM and I'd rather not mess with
the package management system. Can I use the library without
installing it in the same directory tree as boost?


Yes, you can. I'm sorry I didn't say this explicitly before.

Unless you need to use memmory-mapped files, streams based on file descriptors
or filters using zlib or libbz2, all you need to do is put boost-1.32.0 and the
iostreams root directory in your include path. You reference the iostreams
headers the same way you would ordinary boost headers, e.g.:

#include <boost/iostreams/operations.hpp>

If you want to use the components mentioned aboce which have a separate .cpp
files, just add the .cpp files to your project, if you are using an IDE, or to
your makefile, and define the preprocessor symbol BOOST_IOSTREAMS_NO_LIB.

Best Regards,
Jonathan
Jul 22 '05 #12
Jonathan Turkanis wrote:
(This is just an illustration; the official version will be more efficient.)
I would be interested to know when you have an official version
available, by the way.

It
could be used as follows:

#include <iostream>
#include <boost/ref.hpp>
#include <boost/iostreams/filtering_istream.hpp>
I think this last should be "#include
<boost/iostreams/filtering_stream.hpp>", no?
....


I'm using the library and the code, but I'm running into a buffering
problem. I'll query the line count and it will be actually too high
because the next several lines have already been processed but not
handed back to the application. Is there a way to work around this glitch?

Thanks for the help so far,
Adam Peterson
Jul 22 '05 #13

"Adam H. Peterson" <ah**@email.byu.edu> wrote in message
news:cq***********@acs2.byu.edu...
Jonathan Turkanis wrote:
(This is just an illustration; the official version will be more efficient.)
I would be interested to know when you have an official version
available, by the way.


I'll email you when the next version is available. It won't be "official" until
Boost 1.33 is released, but I will be adding it to Boost CVS soon.
It
could be used as follows:

#include <iostream>
#include <boost/ref.hpp>
#include <boost/iostreams/filtering_istream.hpp>


I think this last should be "#include
<boost/iostreams/filtering_stream.hpp>", no?


Right.
I'm using the library and the code, but I'm running into a buffering
problem. I'll query the line count and it will be actually too high
because the next several lines have already been processed but not
handed back to the application. Is there a way to work around this glitch?
I believe if you set the buffer size to zero when you add the filter, you should
get the actual number of lines read:

filtering_istream in;
in.push(line_counter(), 0);
in.push(cin);

Please let me know if this works, including whether it slows things down too
much.
Thanks for the help so far,
Adam Peterson


Jonathan
Jul 22 '05 #14
Jonathan Turkanis wrote:
I'm using the library and the code, but I'm running into a buffering
problem. I'll query the line count and it will be actually too high
because the next several lines have already been processed but not
handed back to the application. Is there a way to work around this glitch?

I believe if you set the buffer size to zero when you add the filter, you should
get the actual number of lines read:

filtering_istream in;
in.push(line_counter(), 0);
in.push(cin);

Please let me know if this works, including whether it slows things down too
much.


That appears to work fine. I'm not noticing any performance difference,
and I wasn't really expecting one either. I think buffering only makes
a difference when interfacing with block I/O devices, so by the time you
get past the original stream source it probably wouldn't help you any.

In any event, I think any performance loss for my purpose(s) would be
par for composing an alternate solution.

FYI, I get some warnings when I compile:
/.../boost/iostreams/categories.hpp:102: warning: virtual base
`boost::io::input_seekable' inaccessible in `boost::io::iostream_tag'
due to ambiguity
/.../boost/iostreams/categories.hpp:102: warning: virtual base
`boost::io::device_tag' inaccessible in `boost::io::iostream_tag' due to
ambiguity
/.../boost/iostreams/categories.hpp:102: warning: virtual base
`boost::io::output_seekable' inaccessible in `boost::io::iostream_tag'
due to ambiguity

They look like design warnings for choices not likely to be made, but I
thought I'd pass them along anyway in case you care.

Thanks,
Adam Peterson
Jul 22 '05 #15
Adam Peterson wrote:
Jonathan Turkanis wrote:
I'm using the library and the code, but I'm running into a buffering
problem. I'll query the line count and it will be actually too high
because the next several lines have already been processed but not
handed back to the application. Is there a way to work around this
glitch?

I believe if you set the buffer size to zero when you add the
filter, you should get the actual number of lines read:

filtering_istream in;
in.push(line_counter(), 0);
in.push(cin);

Please let me know if this works, including whether it slows things
down too much.


That appears to work fine. I'm not noticing any performance
difference, and I wasn't really expecting one either. I think
buffering only makes a difference when interfacing with block I/O
devices, so by the time you get past the original stream source it
probably wouldn't help you any.


I expect buffering to help a bit in with filters, since instead of calling a
virtual stream buffer function every character it happens only once every 128
characters or so. You're right that the gain can be much more significant when
you're accessing a device. Anyway, I'm very glad to see you haven't experienced
any performance loss.
In any event, I think any performance loss for my purpose(s) would be
par for composing an alternate solution.

FYI, I get some warnings when I compile:
/.../boost/iostreams/categories.hpp:102: warning: virtual base
`boost::io::input_seekable' inaccessible in `boost::io::iostream_tag'
due to ambiguity
/.../boost/iostreams/categories.hpp:102: warning: virtual base
`boost::io::device_tag' inaccessible in `boost::io::iostream_tag' due
to ambiguity
/.../boost/iostreams/categories.hpp:102: warning: virtual base
`boost::io::output_seekable' inaccessible in `boost::io::iostream_tag'
due to ambiguity

They look like design warnings for choices not likely to be made, but
I thought I'd pass them along anyway in case you care.


I think this can be fixed by adding a few more 'virtual's. Thanks.

Best Regards,
Jonathan
Jul 22 '05 #16

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

Similar topics

2
3077
by: Peter Wright | last post by:
Hi all. Hopefully this should demonstrate the problem I'm having: http://flooble.net/~pete/focus-problem-demo/ (I'm testing it in Mozilla only, but I'm not sure if it's actually a...
7
4070
by: Generic Usenet Account | last post by:
I am trying to set up a delimiter character string for the input stream such that the delimiter string is "skipped over" in the input stream. Can someone suggest how to do this with some sample...
2
3977
by: Senthil | last post by:
Hi, The need is to read each line in a text file and based on the read data decision has to be taken whether to reposition the file pointer. The StreamReader.Position does not give current...
5
7360
by: HttpWebRequest | last post by:
I am trying to get tracking information from UPS web site without much luck. I got this working in VB 60 without any problems by using WinInet functions Here my test program. We need to get...
2
7715
by: Danny Gagne | last post by:
I'm currently working an .net application (I can use 1.1 or 2.0 if needed) that needs to read a wsdl file and generate another piece of code that can use it. I'm encountering a problem where I...
3
18803
by: sosij.morris | last post by:
Hi. I'm trying to find some tutorial-type information on using scanf's regular-expression subset for parsing - to no avail so far. I've looked through quite a few posts to clc, but none that...
1
1452
by: robert.oschler | last post by:
What's a good way to send tracking information to my server when a FORM submission occurs? Right now I build a URL that goes to a server side script that records the information. Then I set an IMG...
1
1253
by: =?Utf-8?B?SHVzYW0=?= | last post by:
Hi EveryBody: Is it true that when I want to sniff a certine IP from my machine that I have to be apart of network, and If some security Devices such as Firewall and routers if them configuered...
77
3278
by: arnuld | last post by:
1st I think of creating an array of pointers of size 100 as this is the maximum input I intend to take. I can create a fixed size array but in the end I want my array to expand at run-time to fit...
0
7138
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
7418
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
1
7075
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
5662
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
1
5063
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
4737
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
3222
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
1
781
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
446
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence...

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.