open_toontown_panda3d/dtool/src/dtoolutil/pfstreamBuf.cxx

163 lines
4.2 KiB
C++

// Filename: pfstreamBuf.cxx
// Created by: cary (12Dec00)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////
#include "pfstreamBuf.h"
#include <assert.h>
#ifndef HAVE_STREAMSIZE
// Some compilers (notably SGI) don't define this for us
typedef int streamsize;
#endif /* HAVE_STREAMSIZE */
PipeStreamBuf::PipeStreamBuf(PipeStreamBuf::Direction dir) : _dir(dir),
_pipe((FILE*)0L) {
#ifndef WIN32_VC
// taken from Dr. Ose.
// These lines, which are essential on Irix and Linux, seem to be
// unnecessary and not understood on Windows.
allocate();
assert((dir == Input) || (dir == Output));
if (dir == Input) {
// cerr << "allocated reserve is " << blen() << " bytes long" << endl;
setg(base(), ebuf(), ebuf());
} else {
setp(base(), ebuf());
}
#endif /* WIN32_VC */
}
PipeStreamBuf::~PipeStreamBuf(void) {
if (_pipe != (FILE*)0L) {
sync();
flush();
// any other cleanup needed (pclose, etc)
pclose(_pipe);
}
}
void PipeStreamBuf::flush(void) {
assert(_pipe != (FILE*)0L);
if (_dir == Output) {
write_chars("", 0, true);
}
}
void PipeStreamBuf::command(const string cmd) {
assert(_pipe == (FILE*)0L);
const char *typ = (_dir == Output)?"w":"r";
_pipe = popen(cmd.c_str(), typ);
}
int PipeStreamBuf::overflow(int c) {
assert(_pipe != (FILE*)0L);
assert(_dir == Output);
streamsize n = pptr() - pbase();
if (n != 0) {
write_chars(pbase(), n, false);
pbump(-n); // reset pptr()
}
if (c != EOF) {
// write one more character
char ch = c;
write_chars(&ch, 1, false);
}
return 0;
}
int PipeStreamBuf::sync(void) {
assert(_pipe != (FILE*)0L);
if (_dir == Output) {
streamsize n = pptr() - pbase();
write_chars(pbase(), n, false);
pbump(-n);
} else {
streamsize n = egptr() - gptr();
if (n != 0) {
gbump(n); // flush all our stored input away
cerr << "pfstream tossed out " << n << " bytes" << endl;
}
}
return 0;
}
int PipeStreamBuf::underflow(void) {
assert(_pipe != (FILE*)0L);
assert(_dir == Input);
if ((eback() == (char*)0L) || (gptr() == (char*)0L) ||
(egptr() == (char*)0L)) {
// must be in win32
char* buf = new char[4096];
char* ebuf = &(buf[4096]);
setg(buf, ebuf, ebuf);
}
if (gptr() < egptr()) {
char c = *(gptr());
return c;
}
if (feof(_pipe) != 0)
return EOF;
#ifdef WIN32_VC
size_t len = 4096;
#else /* WIN32_VC */
size_t len = ebuf() - base();
#endif /* WIN32_VC */
char* buf = new char[len];
size_t n = fread(buf, 1, len, _pipe);
int ret = buf[0];
if (n == 0)
ret = EOF;
else {
#ifdef WIN32_VC
memcpy(eback()+(len-n), buf, n);
#else /* WIN32_VC */
memcpy(base()+(len-n), buf, n);
#endif /* WIN32_VC */
gbump(-((int)n));
}
delete buf;
return ret;
}
void PipeStreamBuf::write_chars(const char* start, int length, bool flush) {
assert(_dir == Output);
size_t orig = _line_buffer.length();
string latest(start, length);
string line;
if (flush) {
// if we're going to flush the stream now, we dump the whole thing
// reguardless of whether we have reached end-of-line.
line = _line_buffer + latest;
_line_buffer = "";
} else {
// Otherwise, we check for the end-of-line character.
_line_buffer += latest;
size_t eol = _line_buffer.rfind('\n', orig);
if (eol != string::npos) {
line = _line_buffer.substr(0, eol+1);
_line_buffer = _line_buffer.substr(eol+1);
}
}
// now output 'line'
size_t wrote = fwrite(line.c_str(), 1, line.length(), _pipe);
if (wrote != line.length())
cerr << "wrote only " << wrote << " of " << line.length()
<< " bytes to pipe" << endl;
fflush(_pipe);
}