Files
Phoenix/src/stream_input.cpp

162 lines
4.2 KiB
C++

//--------------------------------------------------------------------------
static PyObject* wxPyGetMethod(PyObject* py, char* name)
{
if (!PyObject_HasAttrString(py, name))
return NULL;
PyObject* o = PyObject_GetAttrString(py, name);
if (!PyMethod_Check(o) && !PyCFunction_Check(o)) {
Py_DECREF(o);
return NULL;
}
return o;
}
#define wxPyBlock_t_default PyGILState_UNLOCKED
// This class can wrap a Python file-like object and allow it to be used
// as a wxInputStream.
class wxPyInputStream : public wxInputStream
{
public:
// Make sure there is at least a read method
static bool Check(PyObject* fileObj)
{
PyObject* method = wxPyGetMethod(fileObj, "read");
bool rval = method != NULL;
Py_XDECREF(method);
return rval;
}
wxPyInputStream(PyObject* fileObj, bool block=true)
{
m_block = block;
wxPyThreadBlocker blocker(m_block);
m_read = wxPyGetMethod(fileObj, "read");
m_seek = wxPyGetMethod(fileObj, "seek");
m_tell = wxPyGetMethod(fileObj, "tell");
}
virtual ~wxPyInputStream()
{
wxPyThreadBlocker blocker(m_block);
Py_XDECREF(m_read);
Py_XDECREF(m_seek);
Py_XDECREF(m_tell);
}
wxPyInputStream(const wxPyInputStream& other)
{
wxPyThreadBlocker blocker;
m_read = other.m_read;
m_seek = other.m_seek;
m_tell = other.m_tell;
m_block = other.m_block;
Py_INCREF(m_read);
Py_INCREF(m_seek);
Py_INCREF(m_tell);
}
protected:
// implement base class virtuals
wxFileOffset GetLength() const
{
wxPyInputStream* self = (wxPyInputStream*)this; // cast off const
if (m_seek && m_tell) {
wxFileOffset temp = self->OnSysTell();
wxFileOffset ret = self->OnSysSeek(0, wxFromEnd);
self->OnSysSeek(temp, wxFromStart);
return ret;
}
else
return wxInvalidOffset;
}
size_t OnSysRead(void *buffer, size_t bufsize)
{
if (bufsize == 0)
return 0;
wxPyThreadBlocker blocker;
PyObject* arglist = Py_BuildValue("(i)", bufsize);
PyObject* result = PyObject_CallObject(m_read, arglist);
Py_DECREF(arglist);
size_t o = 0;
if ((result != NULL) && PyBytes_Check(result)) {
o = PyBytes_Size(result);
if (o == 0)
m_lasterror = wxSTREAM_EOF;
if (o > bufsize)
o = bufsize;
memcpy((char*)buffer, PyBytes_AsString(result), o); // strings only, not unicode...
Py_DECREF(result);
}
else
m_lasterror = wxSTREAM_READ_ERROR;
return o;
}
size_t OnSysWrite(const void *buffer, size_t bufsize)
{
m_lasterror = wxSTREAM_WRITE_ERROR;
return 0;
}
wxFileOffset OnSysSeek(wxFileOffset off, wxSeekMode mode)
{
wxPyThreadBlocker blocker;
PyObject* arglist = PyTuple_New(2);
if (sizeof(wxFileOffset) > sizeof(long))
// wxFileOffset is a 64-bit value...
PyTuple_SET_ITEM(arglist, 0, PyLong_FromLongLong(off));
else
PyTuple_SET_ITEM(arglist, 0, wxPyInt_FromLong(off));
PyTuple_SET_ITEM(arglist, 1, wxPyInt_FromLong(mode));
PyObject* result = PyObject_CallObject(m_seek, arglist);
Py_DECREF(arglist);
Py_XDECREF(result);
return OnSysTell();
}
wxFileOffset OnSysTell() const
{
wxPyThreadBlocker blocker;
PyObject* arglist = Py_BuildValue("()");
PyObject* result = PyObject_CallObject(m_tell, arglist);
Py_DECREF(arglist);
wxFileOffset o = 0;
if (result != NULL) {
if (PyLong_Check(result))
o = PyLong_AsLongLong(result);
else
o = wxPyInt_AsLong(result);
Py_DECREF(result);
};
return o;
}
bool IsSeekable() const
{
return (m_seek != NULL);
}
private:
PyObject* m_read;
PyObject* m_seek;
PyObject* m_tell;
bool m_block;
};
//--------------------------------------------------------------------------