mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-30 16:00:55 +00:00
426 lines
7 KiB
C
426 lines
7 KiB
C
|
/*
|
||
|
Author: Marcus Boerger <helly@users.sourceforge.net>
|
||
|
*/
|
||
|
|
||
|
/* $Id: stream_lc.h,v 1.10 2006/02/26 20:36:09 helly Exp $ */
|
||
|
|
||
|
#ifndef _stream_lc_h
|
||
|
#define _stream_lc_h
|
||
|
|
||
|
#include <iosfwd>
|
||
|
#include <fstream>
|
||
|
#include <assert.h>
|
||
|
#include <stdio.h>
|
||
|
|
||
|
namespace re2c
|
||
|
{
|
||
|
|
||
|
template<class _E, class _Tr = std::char_traits<_E> >
|
||
|
class basic_null_streambuf
|
||
|
: public std::basic_streambuf<_E, _Tr>
|
||
|
{
|
||
|
public:
|
||
|
basic_null_streambuf()
|
||
|
: std::basic_streambuf<_E, _Tr>()
|
||
|
{
|
||
|
}
|
||
|
};
|
||
|
|
||
|
typedef basic_null_streambuf<char> null_streambuf;
|
||
|
|
||
|
template<class _E, class _Tr = std::char_traits<_E> >
|
||
|
class basic_null_stream
|
||
|
: public std::basic_ostream<_E, _Tr>
|
||
|
{
|
||
|
public:
|
||
|
basic_null_stream()
|
||
|
: std::basic_ostream<_E, _Tr>(null_buf = new basic_null_streambuf<_E, _Tr>())
|
||
|
{
|
||
|
}
|
||
|
|
||
|
virtual ~basic_null_stream()
|
||
|
{
|
||
|
delete null_buf;
|
||
|
}
|
||
|
|
||
|
basic_null_stream& put(_E)
|
||
|
{
|
||
|
// nothing to do
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
basic_null_stream& write(const _E *, std::streamsize)
|
||
|
{
|
||
|
// nothing to do
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
basic_null_streambuf<_E, _Tr> * null_buf;
|
||
|
};
|
||
|
|
||
|
typedef basic_null_stream<char> null_stream;
|
||
|
|
||
|
class line_number
|
||
|
{
|
||
|
public:
|
||
|
virtual ~line_number()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
virtual uint get_line() const = 0;
|
||
|
};
|
||
|
|
||
|
template<class _E, class _Tr = std::char_traits<_E> >
|
||
|
class basic_filebuf_lc
|
||
|
: public std::basic_streambuf<_E, _Tr>
|
||
|
, public line_number
|
||
|
{
|
||
|
public:
|
||
|
typedef std::basic_streambuf<_E, _Tr> _Mybase;
|
||
|
typedef basic_filebuf_lc<_E, _Tr> _Myt;
|
||
|
typedef _E char_type;
|
||
|
typedef _Tr traits_type;
|
||
|
typedef typename _Tr::int_type int_type;
|
||
|
typedef typename _Tr::pos_type pos_type;
|
||
|
typedef typename _Tr::off_type off_type;
|
||
|
|
||
|
basic_filebuf_lc(FILE *_fp = 0)
|
||
|
: _Mybase()
|
||
|
, fp(_fp)
|
||
|
, must_close(false)
|
||
|
, fline(1)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
virtual ~basic_filebuf_lc()
|
||
|
{
|
||
|
sync();
|
||
|
if (must_close)
|
||
|
{
|
||
|
close();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
uint get_line() const
|
||
|
{
|
||
|
return fline + 1;
|
||
|
}
|
||
|
|
||
|
bool is_open() const
|
||
|
{
|
||
|
return fp != 0;
|
||
|
}
|
||
|
|
||
|
_Myt* open(const char *filename, std::ios_base::openmode mode = std::ios_base::out)
|
||
|
{
|
||
|
if (fp != 0)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
const char * fmode = (mode & std::ios_base::out)
|
||
|
? "wt"
|
||
|
: "rt";
|
||
|
if ((fp = fopen(filename, fmode)) == 0)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
must_close = true;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
_Myt* open(FILE * _fp)
|
||
|
{
|
||
|
if (fp != 0)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
fp = _fp;
|
||
|
must_close = false;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
_Myt* close()
|
||
|
{
|
||
|
sync();
|
||
|
|
||
|
if (fp == 0 || fclose(fp) != 0)
|
||
|
{
|
||
|
fp = 0;
|
||
|
return 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
fp = 0;
|
||
|
return this;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
|
||
|
virtual int_type overflow(int_type c = _Tr::eof())
|
||
|
{
|
||
|
if (c == '\n')
|
||
|
{
|
||
|
++fline;
|
||
|
}
|
||
|
if (_Tr::eq_int_type(_Tr::eof(), c))
|
||
|
{
|
||
|
return _Tr::not_eof(c);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
buffer += _Tr::to_char_type(c);
|
||
|
return c;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
virtual int_type pbackfail(int_type c = _Tr::eof())
|
||
|
{
|
||
|
assert(0);
|
||
|
c = 0;
|
||
|
return _Tr::eof();
|
||
|
}
|
||
|
|
||
|
virtual int_type underflow() // don't point past it
|
||
|
{
|
||
|
int c;
|
||
|
|
||
|
if (buffer.length())
|
||
|
{
|
||
|
return buffer[0];
|
||
|
}
|
||
|
if (fp == 0 || ((c = fgetc(fp)) == EOF))
|
||
|
{
|
||
|
return _Tr::eof();
|
||
|
}
|
||
|
buffer += (char)c;
|
||
|
return c;
|
||
|
}
|
||
|
|
||
|
virtual int_type uflow() // point past it
|
||
|
{
|
||
|
int c;
|
||
|
|
||
|
if (buffer.length())
|
||
|
{
|
||
|
c = buffer[0];
|
||
|
buffer.erase(0, 1);
|
||
|
return c;
|
||
|
}
|
||
|
if (fp == 0 || ((c = fgetc(fp)) == EOF))
|
||
|
{
|
||
|
return _Tr::eof();
|
||
|
}
|
||
|
else if (c == '\n')
|
||
|
{
|
||
|
++fline;
|
||
|
}
|
||
|
return c;
|
||
|
}
|
||
|
|
||
|
#if 0
|
||
|
virtual std::streamsize xsgetn(_E* buf, std::streamsize n)
|
||
|
{
|
||
|
std::streamsize r = 0;
|
||
|
while(n--)
|
||
|
{
|
||
|
int_type c = underflow();
|
||
|
if (_Tr::eq_int_type(_Tr::eof(), c))
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
buf[r++] = c;
|
||
|
}
|
||
|
buf[r] = '\0';
|
||
|
return r;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
virtual pos_type seekoff(off_type off, std::ios_base::seekdir whence,
|
||
|
std::ios_base::openmode = (std::ios_base::openmode)(std::ios_base::in | std::ios_base::out))
|
||
|
{
|
||
|
return fseek(fp, (long)off, whence);
|
||
|
}
|
||
|
|
||
|
virtual pos_type seekpos(pos_type fpos,
|
||
|
std::ios_base::openmode = (std::ios_base::openmode)(std::ios_base::in | std::ios_base::out))
|
||
|
{
|
||
|
return fseek(fp, (long)fpos, SEEK_SET);
|
||
|
}
|
||
|
|
||
|
virtual _Mybase * setbuf(_E *, std::streamsize)
|
||
|
{
|
||
|
assert(0);
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
virtual int sync()
|
||
|
{
|
||
|
fwrite(buffer.c_str(), sizeof(_E), buffer.length(), fp);
|
||
|
buffer.clear();
|
||
|
return fp == 0
|
||
|
|| _Tr::eq_int_type(_Tr::eof(), overflow())
|
||
|
|| 0 <= fflush(fp) ? 0 : -1;
|
||
|
}
|
||
|
|
||
|
virtual std::streamsize xsputn(const _E *buf, std::streamsize cnt)
|
||
|
{
|
||
|
fwrite(buffer.c_str(), sizeof(_E), buffer.length(), fp);
|
||
|
buffer.clear();
|
||
|
/*fline += std::count(buf, buf + cnt, '\n');*/
|
||
|
for (std::streamsize pos = 0; pos < cnt; ++pos)
|
||
|
{
|
||
|
if (buf[pos] == '\n')
|
||
|
{
|
||
|
++fline;
|
||
|
}
|
||
|
}
|
||
|
return fwrite(buf, sizeof(_E), cnt, fp);
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
|
||
|
FILE * fp;
|
||
|
bool must_close;
|
||
|
uint fline;
|
||
|
std::basic_string<_E, _Tr> buffer;
|
||
|
};
|
||
|
|
||
|
typedef basic_filebuf_lc<char> filebuf_lc;
|
||
|
|
||
|
template<
|
||
|
class _E,
|
||
|
class _BaseStream,
|
||
|
std::ios_base::openmode _DefOpenMode,
|
||
|
class _Tr = std::char_traits<_E> >
|
||
|
class basic_fstream_lc
|
||
|
: public _BaseStream
|
||
|
, public line_number
|
||
|
{
|
||
|
public:
|
||
|
typedef basic_fstream_lc<_E, _BaseStream, _DefOpenMode, _Tr> _Myt;
|
||
|
typedef std::basic_ios<_E, _Tr> _Myios;
|
||
|
typedef _BaseStream _Mybase;
|
||
|
typedef basic_filebuf_lc<_E, _Tr> _Mybuf;
|
||
|
|
||
|
basic_fstream_lc()
|
||
|
: _Mybase(mybuf = new _Mybuf())
|
||
|
{
|
||
|
}
|
||
|
|
||
|
virtual ~basic_fstream_lc()
|
||
|
{
|
||
|
delete mybuf;
|
||
|
}
|
||
|
|
||
|
bool is_open() const
|
||
|
{
|
||
|
return mybuf->is_open();
|
||
|
}
|
||
|
|
||
|
_Myt& open(const char * filename, std::ios_base::openmode mode = _DefOpenMode)
|
||
|
{
|
||
|
if ((mode & _DefOpenMode) == 0 || mybuf->open(filename, mode) == 0)
|
||
|
{
|
||
|
_Myios::setstate(std::ios_base::failbit);
|
||
|
}
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
_Myt& open(FILE *fp)
|
||
|
{
|
||
|
if (mybuf->open(fp) == 0)
|
||
|
{
|
||
|
_Myios::setstate(std::ios_base::failbit);
|
||
|
}
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
void close()
|
||
|
{
|
||
|
if (mybuf->close() == 0)
|
||
|
{
|
||
|
_Myios::setstate(std::ios_base::failbit);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
uint get_line() const
|
||
|
{
|
||
|
return mybuf->get_line();
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
mutable _Mybuf *mybuf;
|
||
|
};
|
||
|
|
||
|
template<class _E, class _Tr = std::char_traits<_E> >
|
||
|
class basic_ofstream_lc
|
||
|
: public basic_fstream_lc<_E, std::basic_ostream<_E, _Tr>, std::ios_base::out, _Tr>
|
||
|
{
|
||
|
};
|
||
|
|
||
|
typedef basic_ofstream_lc<char> ofstream_lc;
|
||
|
|
||
|
template<class _E, class _Tr = std::char_traits<_E> >
|
||
|
class basic_ifstream_lc
|
||
|
: public basic_fstream_lc<_E, std::basic_istream<_E, _Tr>, std::ios_base::in, _Tr>
|
||
|
{
|
||
|
};
|
||
|
|
||
|
typedef basic_ifstream_lc<char> ifstream_lc;
|
||
|
|
||
|
class file_info
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
static std::string escape(const std::string& _str)
|
||
|
{
|
||
|
std::string str(_str);
|
||
|
size_t l = str.length();
|
||
|
for (size_t p = 0; p < l; ++p)
|
||
|
{
|
||
|
if (str[p] == '\\')
|
||
|
{
|
||
|
str.insert(++p, "\\");
|
||
|
++l;
|
||
|
}
|
||
|
}
|
||
|
return str;
|
||
|
}
|
||
|
|
||
|
file_info()
|
||
|
: ln(NULL)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
file_info(const std::string& _fname, const line_number* _ln, bool _escape = true)
|
||
|
: fname(_escape ? escape(_fname) : _fname)
|
||
|
, ln(_ln)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
file_info(const file_info& oth, const line_number* _ln = NULL)
|
||
|
: fname(oth.fname)
|
||
|
, ln(_ln)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
file_info& operator = (const file_info& oth)
|
||
|
{
|
||
|
*(const_cast<std::string*>(&this->fname)) = oth.fname;
|
||
|
ln = oth.ln;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
const std::string fname;
|
||
|
const line_number* ln;
|
||
|
};
|
||
|
|
||
|
std::ostream& operator << (std::ostream& o, const file_info& li);
|
||
|
|
||
|
} // end namespace re2c
|
||
|
|
||
|
#endif /* _stream_lc_h */
|