/* Copyright (c) 1997-2006
Ewgenij Gawrilow, Michael Joswig (Technische Universitaet Berlin, Germany)
http://www.math.tu-berlin.de/polymake, mailto:polymake@math.tu-berlin.de
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version: http://www.gnu.org/licenses/gpl.txt.
This program 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 General Public License for more details.
*/
#ifndef _POLYMAKE_CHARBUFFER_H
#define _POLYMAKE_CHARBUFFER_H "$Project: polymake $$Id: CharBuffer.h 7461 2006-11-12 23:25:23Z gawrilow $"
#include <sys/types.h>
#include <cctype>
#include <cstring>
#include <socketstream.h>
namespace pm {
class CharBuffer : public std::streambuf_with_input_width {
private:
// never create
CharBuffer();
~CharBuffer();
public:
typedef std::streambuf::traits_type traits_type;
typedef std::streambuf::int_type int_type;
static void skip_all(std::streambuf *_buf)
{
CharBuffer *buf=static_cast<CharBuffer*>(_buf);
PM_SET_BUF_GET_CUR_END(buf);
}
static int seek_forward(std::streambuf *_buf, int offset)
{
CharBuffer *buf=static_cast<CharBuffer*>(_buf);
const int_type eof_char=traits_type::eof();
if (buf->gptr()+offset >= buf->egptr() && buf->underflow()==eof_char)
return eof_char;
return buf->gptr()[offset];
}
static int next_ws(std::streambuf *_buf, int offset=0, bool report_eof=true)
{
CharBuffer *buf=static_cast<CharBuffer*>(_buf);
const int_type eof_char=traits_type::eof();
for (int_type c; (c=seek_forward(buf, offset))!=eof_char; ++offset)
if (isspace(c)) return offset;
return report_eof ? -1 : offset;
}
static int next_non_ws(std::streambuf *_buf, int offset=0)
{
CharBuffer *buf=static_cast<CharBuffer*>(_buf);
const int_type eof_char=traits_type::eof();
for (int_type c; (c=seek_forward(buf, offset))!=eof_char; ++offset)
if (!isspace(c)) return offset;
return -1;
}
static int skip_ws(std::streambuf *_buf)
{
CharBuffer *buf=static_cast<CharBuffer*>(_buf);
int i=next_non_ws(buf);
if (i<0) {
skip_all(buf);
return -1;
} else {
buf->gbump(i);
return 0;
}
}
static int find_char_forward(std::streambuf *_buf, char c, int offset=0)
{
CharBuffer *buf=static_cast<CharBuffer*>(_buf);
const int_type eof_char=traits_type::eof();
if (seek_forward(buf, offset) != eof_char) {
do {
if (char *found=(char*)memchr(buf->gptr()+offset, c, buf->egptr()-(buf->gptr()+offset)))
return found-buf->gptr();
offset=buf->egptr()-buf->gptr();
} while (buf->underflow() != eof_char);
}
return -1;
}
static int_type ignore(std::streambuf *_buf, char c)
{
CharBuffer *buf=static_cast<CharBuffer*>(_buf);
const int_type eof_char=traits_type::eof();
int_type next_c;
while ((next_c=seek_forward(buf,0)) != eof_char) {
if (next_c==c) {
buf->gbump(1);
break;
}
if (char *found=(char*)memchr(buf->gptr(), c, buf->egptr()-buf->gptr())) {
buf->gbump(found-buf->gptr()+1);
return c;
}
PM_SET_BUF_GET_CUR_END(buf);
}
return next_c;
}
static int find_string_forward(std::streambuf *_buf, const char *c, int len, int offset)
{
CharBuffer *buf=static_cast<CharBuffer*>(_buf);
const int_type eof_char=traits_type::eof();
while ((offset=find_char_forward(buf, c[0], offset)) >= 0 &&
seek_forward(buf, offset+len-1) != eof_char) {
if (!memcmp(buf->gptr()+offset, c, len)) return offset;
++offset;
}
return -1;
}
static int count_char(std::streambuf *_buf, char c)
{
CharBuffer *buf=static_cast<CharBuffer*>(_buf);
char *start=buf->gptr(), *end=buf->egptr();
int cnt=0;
while ((start=(char*)memchr(start, c, end-start)) != 0) {
++cnt; ++start;
}
return cnt;
}
static int count_lines(std::streambuf *buf)
{
if (skip_ws(buf)<0) return 0;
return count_char(buf,'\n');
}
static int matching_brace (std::streambuf *buf, char opening, char closing, int offset=0);
static int get_string(std::streambuf *buf, std::string&, char delim);
static char* get_ptr(std::streambuf *_buf)
{
CharBuffer *buf=static_cast<CharBuffer*>(_buf);
return buf->gptr();
}
static char* end_get_ptr(std::streambuf *_buf)
{
CharBuffer *buf=static_cast<CharBuffer*>(_buf);
return buf->egptr();
}
static void get_bump(std::streambuf *_buf, int offset)
{
CharBuffer *buf=static_cast<CharBuffer*>(_buf);
buf->gbump(offset);
}
static void set_end_get_ptr(std::streambuf *_buf, char *end)
{
CharBuffer *buf=static_cast<CharBuffer*>(_buf);
PM_SET_BUF_GET_END(buf,end);
}
static void set_end_get_ptr(std::streambuf *_buf, int offset)
{
CharBuffer *buf=static_cast<CharBuffer*>(_buf);
PM_SET_BUF_GET_END_OFF(buf,offset);
}
static void set_get_and_end_ptr(std::streambuf *_buf, char *get, char *end)
{
CharBuffer *buf=static_cast<CharBuffer*>(_buf);
PM_SET_BUF_GET_CUR(buf,get,end);
}
static const char* get_input_limit(std::streambuf *_buf)
{
return static_cast<CharBuffer*>(_buf)->input_limit;
}
};
} // end namespace pm
#endif // _POLYMAKE_CHARBUFFER_H
// Local Variables:
// mode:C++
// End:
syntax highlighted by Code2HTML, v. 0.9.1