// This is part of the iostream library, providing -*- C++ -*- input/output.
// Copyright (C) 1991 Per Bothner.
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Library General Public License for more details.
// You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the Free
// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
// A parsebuf is a streambuf optimized for scanning text files.
// It keeps track of line and column numbers.
// It is guaranteed to remember the entire current line,
// as well the '\n'-s on either side of it (if they exist).
// You can arbitrarily seek (or unget) within this extended line.
// Other backward seeks are not supported.
// Normal read semantics are supported (and hence istream operators like >>).
class parsebuf
: public backupbuf
{
_G_fpos_t pos_at_line_start
;
unsigned long __line_number
;
// Return column number (raw - don't handle tabs etc).
// Retult can be -1, meaning: at '\n' before current line.
virtual int tell_in_line();
// seek to (raw) column I in current line.
// Result is new (raw) column position - differs from I if unable to seek.
// Seek to -1 tries to seek to before previous LF.
virtual int seek_in_line(int i
);
// Note: there is no "current line" initially, until something is read.
// Current line number, starting with 0.
// If tell_in_line()==-1, then line number of next line.
int line_number() { return __line_number
; }
// Length of current line, not counting either '\n'.
int line_length() { return _line_length
; }
// Current line - not a copy, so file ops may trash it.
virtual char* current_line();
virtual streampos
seekoff(streamoff
, _seek_dir
, int mode
=ios::in
|ios::out
);
virtual streambuf
* setbuf(char* p
, int len
);
parsebuf() : backupbuf() { chain
= NULL
;
__line_number
= 0; pos_at_line_start
= 0; _line_length
= -1; }
virtual int pbackfail(int c
);
// A string_parsebuf is a parsebuf whose source is a fixed string.
class string_parsebuf
: public parsebuf
{
string_parsebuf(char *str
, int len
, int delete_at_close
=0);
virtual char* current_line();
virtual int seek_in_line(int i
);
virtual int tell_in_line();
char *left() const { return base(); }
char *right() const { return ebuf(); }
// streampos seekoff(streamoff, _seek_dir, int);
// A func_parsebuf calls a given function to get new input.
// Each call returns an entire NUL-terminated line (without the '\n').
// That line has been allocated with malloc(), not new.
// The interface is tailored to the GNU readline library.
// char* DoReadLine(void* arg)
// char *line = readline((char*)arg); /* 'arg' is used as prompt. */
// if line == NULL) { putc('\n', stderr); return NULL; }
// if (line[0] != '\0') add_history(line);
// char PromptBuffer[100] = "> ";
// func_parsebuf my_stream(DoReadLine, PromptBuffer);
typedef char *(*CharReader
)(void *arg
);
class func_parsebuf
: public parsebuf
{
int backed_up_to_newline
;
func_parsebuf(CharReader func
, void *argm
= NULL
);
virtual int tell_in_line();
virtual int seek_in_line(int i
);
virtual char* current_line();
// A general_parsebuf is a parsebuf which gets its input from some
// other streambuf. It explicitly buffers up an entire line.
class general_parsebuf
: public parsebuf
{
int delete_buf
; // Delete sbuf when destroying this.
general_parsebuf(streambuf
*buf
, int delete_arg_buf
= 0);
virtual int tell_in_line();
virtual int seek_in_line(int i
);
virtual char* current_line();
class parsestream
: public istream
{
short _first
; // of the two marks; either 0 or 1
int first() { return _first
; }
int second() { return 1-_first
; }
int line_length() { marks
[second
].delta(marks
[first
]); }
int line_length() { marks
[second
].delta(marks
[first
]); }
#endif /*!defined(PARSESTREAM_H)*/