Merge branch 'master' into master

This commit is contained in:
sliptonic 2016-06-12 19:37:46 -05:00 committed by GitHub
commit 0f46fd6636
2 changed files with 93 additions and 40 deletions

View File

@ -524,12 +524,22 @@ IODeviceIStreambuf::seekpos(std::streambuf::pos_type pos,
// --------------------------------------------------------- // ---------------------------------------------------------
PyStreambuf::PyStreambuf(PyObject* o) : inp(o) // Buffering would make it very fast but it doesn't seem to write all data
//#define PYSTREAM_BUFFERED
// http://www.mr-edd.co.uk/blog/beginners_guide_streambuf
PyStreambuf::PyStreambuf(PyObject* o, std::size_t buf_size, std::size_t put_back)
: inp(o)
, put_back(std::max(put_back, std::size_t(1)))
, buffer(std::max(buf_size, put_back) + put_back)
{ {
Py_INCREF(inp); Py_INCREF(inp);
setg (buffer+pbSize, char *end = &buffer.front() + buffer.size();
buffer+pbSize, setg(end, end, end);
buffer+pbSize); #ifdef PYSTREAM_BUFFERED
char *base = &buffer.front();
setp(base, base + buffer.size() - 1);
#endif
} }
PyStreambuf::~PyStreambuf() PyStreambuf::~PyStreambuf()
@ -540,49 +550,57 @@ PyStreambuf::~PyStreambuf()
std::streambuf::int_type PyStreambuf::underflow() std::streambuf::int_type PyStreambuf::underflow()
{ {
if (gptr() < egptr()) { if (gptr() < egptr()) {
return *gptr(); return traits_type::to_int_type(*gptr());
} }
int numPutback; char *base = &buffer.front();
numPutback = gptr() - eback(); char *start = base;
if (numPutback > pbSize) {
numPutback = pbSize; if (eback() == base) { // true when this isn't the first fill
std::memmove(base, egptr() - put_back, put_back);
start += put_back;
} }
memcpy (buffer+(pbSize-numPutback), gptr()-numPutback, numPutback); std::size_t n;
int num=0;
for (int i=0; i<bufSize; i++) {
char c;
Py::Tuple arg(1); Py::Tuple arg(1);
arg.setItem(0, Py::Int(1)); long len = static_cast<long>(buffer.size() - (start - base));
arg.setItem(0, Py::Long(len));
Py::Callable meth(Py::Object(inp).getAttr("read")); Py::Callable meth(Py::Object(inp).getAttr("read"));
try { try {
Py::Char res(meth.apply(arg)); Py::String res(meth.apply(arg));
c = static_cast<std::string>(res)[0]; std::string c = static_cast<std::string>(res);
num++; n = c.size();
buffer[pbSize+i] = c; if (n == 0) {
return traits_type::eof();
}
std::memcpy(start, &(c[0]), c.size());
} }
catch (Py::Exception& e) { catch (Py::Exception& e) {
e.clear(); e.clear();
if (num == 0) return traits_type::eof();
return EOF;
break;
}
} }
setg (buffer+(pbSize-numPutback), setg(base, start, start + n);
buffer+pbSize, return traits_type::to_int_type(*gptr());
buffer+pbSize+num);
return *gptr();
} }
std::streambuf::int_type std::streambuf::int_type
PyStreambuf::overflow(std::streambuf::int_type c) PyStreambuf::overflow(std::streambuf::int_type ch)
{ {
if (c != EOF) { #ifdef PYSTREAM_BUFFERED
char z = c; if (ch != traits_type::eof()) {
*pptr() = ch;
pbump(1);
if (flushBuffer())
return ch;
}
return traits_type::eof();
#else
if (ch != EOF) {
char z = ch;
try { try {
Py::Tuple arg(1); Py::Tuple arg(1);
@ -596,11 +614,42 @@ PyStreambuf::overflow(std::streambuf::int_type c)
} }
} }
return c; return ch;
#endif
}
int PyStreambuf::sync()
{
#ifdef PYSTREAM_BUFFERED
return flushBuffer() ? 0 : -1;
#else
return std::streambuf::sync();
#endif
}
bool PyStreambuf::flushBuffer()
{
std::ptrdiff_t n = pptr() - pbase();
pbump(-n);
try {
Py::Tuple arg(1);
arg.setItem(0, Py::String(pbase(), n));
Py::Callable meth(Py::Object(inp).getAttr("write"));
meth.apply(arg);
return true;
}
catch(Py::Exception& e) {
e.clear();
return false;
}
} }
std::streamsize PyStreambuf::xsputn (const char* s, std::streamsize num) std::streamsize PyStreambuf::xsputn (const char* s, std::streamsize num)
{ {
#ifdef PYSTREAM_BUFFERED
return std::streambuf::xsputn(s, num);
#else
try { try {
Py::Tuple arg(1); Py::Tuple arg(1);
arg.setItem(0, Py::String(s, num)); arg.setItem(0, Py::String(s, num));
@ -613,6 +662,7 @@ std::streamsize PyStreambuf::xsputn (const char* s, std::streamsize num)
} }
return num; return num;
#endif
} }
// --------------------------------------------------------- // ---------------------------------------------------------

View File

@ -241,19 +241,22 @@ protected:
class BaseExport PyStreambuf : public std::streambuf class BaseExport PyStreambuf : public std::streambuf
{ {
public: public:
PyStreambuf(PyObject* o); PyStreambuf(PyObject* o, std::size_t buf_size = 256, std::size_t put_back = 8);
virtual ~PyStreambuf(); virtual ~PyStreambuf();
protected: protected:
int_type underflow(); int_type underflow();
int_type overflow(int_type c = EOF); int_type overflow(int_type c = EOF);
std::streamsize xsputn (const char* s, std::streamsize num); std::streamsize xsputn (const char* s, std::streamsize num);
int sync();
private:
bool flushBuffer();
private: private:
static const int pbSize = 4;
static const int bufSize = 1024;
char buffer[bufSize+pbSize];
PyObject* inp; PyObject* inp;
const std::size_t put_back;
std::vector<char> buffer;
}; };
class BaseExport Streambuf : public std::streambuf class BaseExport Streambuf : public std::streambuf