mirror of
https://github.com/wxWidgets/Phoenix.git
synced 2026-01-07 20:40:11 +01:00
155 lines
4.0 KiB
C++
155 lines
4.0 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 wxPyOutputStream : public wxOutputStream
|
|
{
|
|
public:
|
|
|
|
// Make sure there is at least a write method
|
|
static bool Check(PyObject* fileObj)
|
|
{
|
|
PyObject* method = wxPyGetMethod(fileObj, "write");
|
|
bool rval = method != NULL;
|
|
Py_XDECREF(method);
|
|
return rval;
|
|
}
|
|
|
|
wxPyOutputStream(PyObject* fileObj, bool block=true)
|
|
{
|
|
m_block = block;
|
|
wxPyThreadBlocker blocker(m_block);
|
|
|
|
m_write = wxPyGetMethod(fileObj, "write");
|
|
m_seek = wxPyGetMethod(fileObj, "seek");
|
|
m_tell = wxPyGetMethod(fileObj, "tell");
|
|
}
|
|
|
|
virtual ~wxPyOutputStream()
|
|
{
|
|
wxPyThreadBlocker blocker(m_block);
|
|
Py_XDECREF(m_write);
|
|
Py_XDECREF(m_seek);
|
|
Py_XDECREF(m_tell);
|
|
}
|
|
|
|
wxPyOutputStream(const wxPyOutputStream& other)
|
|
{
|
|
wxPyThreadBlocker blocker;
|
|
m_write = other.m_write;
|
|
m_seek = other.m_seek;
|
|
m_tell = other.m_tell;
|
|
m_block = other.m_block;
|
|
Py_INCREF(m_write);
|
|
Py_INCREF(m_seek);
|
|
Py_INCREF(m_tell);
|
|
}
|
|
|
|
protected:
|
|
|
|
// implement base class virtuals
|
|
|
|
wxFileOffset GetLength() const
|
|
{
|
|
wxPyOutputStream* self = (wxPyOutputStream*)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)
|
|
{
|
|
m_lasterror = wxSTREAM_READ_ERROR;
|
|
return 0;
|
|
}
|
|
|
|
size_t OnSysWrite(const void *buffer, size_t bufsize)
|
|
{
|
|
if (bufsize == 0)
|
|
return 0;
|
|
|
|
wxPyThreadBlocker blocker;
|
|
PyObject* arglist = PyTuple_New(1);
|
|
PyTuple_SET_ITEM(arglist, 0, PyBytes_FromStringAndSize((char*)buffer, bufsize));
|
|
|
|
PyObject* result = PyObject_CallObject(m_write, arglist);
|
|
Py_DECREF(arglist);
|
|
|
|
if (result != NULL)
|
|
Py_DECREF(result);
|
|
else
|
|
m_lasterror = wxSTREAM_WRITE_ERROR;
|
|
return bufsize;
|
|
}
|
|
|
|
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_write;
|
|
PyObject* m_seek;
|
|
PyObject* m_tell;
|
|
bool m_block;
|
|
};
|
|
|
|
//--------------------------------------------------------------------------
|