How to count lines in streams?

I'd like to parse an ascii file using the standard fstream lib.
If an error occurs during parsing the line number should be displayed.

Since streams usually ignore whitespaces it seems to be tough to do this anyway.
For some reason I do not want to use getline(). Mainly it will return an infinitely long char* when no new line character is in the stream.
fstream gives access to its streambuf and therefore the possibility to scan for special characters. A "dummy" class nlcount is used to store the actual line number and counts the number of new line characters between two function calls as follwing code fragment illustrates:

struct nlcount {
int count;
char *pos;
nlcount(): count(1), pos(0) {}
};

void testfunction(void) {

nlcount nls;

file >> nls >> ... >> nls; // Number of lines will be counted between two calls.

}

The implementation overloads the >> operator for the class nlcount and uses the StreamBufPtr class to get access to the protected functions gptr and setg and to make it possible to store and recover the streambuf position:

class StreamBufPtr : public streambuf {

public:
char_type* GetPtr(void) { return gptr(); }
void SetPtr(char_type* gnext) { setg(eback(), gnext, egptr()); }

};

std::istream& operator>> (std::istream& in, nlcount& nls) {

std::istream::sentry kerberos(in, true);
if (kerberos) {
StreamBufPtr* sbuf=(StreamBufPtr *)in.rdbuf(); // might crash ?
char *ActPtr=sbuf->GetPtr(); // save actual position
if (nls.pos && nls.pos<ActPtr) {
sbuf->SetPtr(nls.pos);
int eof = std::char_traits<char>::eof();
int c = sbuf->sgetc();
for ( ; c != eof && sbuf->GetPtr()<ActPtr; c = sbuf->snextc())
if (c == std::char_traits<char>::to_int_type('\n')) nls.count++;
sbuf->SetPtr(ActPtr);
if (c == eof) in.setstate(std::ios_base::eofbit);
}
nls.pos=ActPtr;
}
return in;
}

Although this solution works with the gcc compiler, it has a major drawback: it will cast the streambuf* into a StreamBufPtr* without any constructor initialization of StreamBufPtr. To my understanding this is not allowed and will possibly crash!? If so, is it possible to construct the class StreamBufPtr with the contents of streambuf to get a properly initialized object?

I would be glad if someone can suppose a better solution or give any comments.

Kind regards,
takatuka
Last edited on
Topic archived. No new replies allowed.