1 //--------------------------------------------------------------------------
2
wxPyGetMethod(PyObject * py,char * name)3 static PyObject* wxPyGetMethod(PyObject* py, char* name)
4 {
5 if (!PyObject_HasAttrString(py, name))
6 return NULL;
7 PyObject* o = PyObject_GetAttrString(py, name);
8 if (!PyMethod_Check(o) && !PyCFunction_Check(o)) {
9 Py_DECREF(o);
10 return NULL;
11 }
12 return o;
13 }
14
15 #define wxPyBlock_t_default PyGILState_UNLOCKED
16
17
18 // This class can wrap a Python file-like object and allow it to be used
19 // as a wxInputStream.
20 class wxPyOutputStream : public wxOutputStream
21 {
22 public:
23
24 // Make sure there is at least a write method
Check(PyObject * fileObj)25 static bool Check(PyObject* fileObj)
26 {
27 PyObject* method = wxPyGetMethod(fileObj, "write");
28 bool rval = method != NULL;
29 Py_XDECREF(method);
30 return rval;
31 }
32
wxPyOutputStream(PyObject * fileObj,bool block=true)33 wxPyOutputStream(PyObject* fileObj, bool block=true)
34 {
35 m_block = block;
36 wxPyThreadBlocker blocker(m_block);
37
38 m_write = wxPyGetMethod(fileObj, "write");
39 m_seek = wxPyGetMethod(fileObj, "seek");
40 m_tell = wxPyGetMethod(fileObj, "tell");
41 }
42
~wxPyOutputStream()43 virtual ~wxPyOutputStream()
44 {
45 wxPyThreadBlocker blocker(m_block);
46 Py_XDECREF(m_write);
47 Py_XDECREF(m_seek);
48 Py_XDECREF(m_tell);
49 }
50
wxPyOutputStream(const wxPyOutputStream & other)51 wxPyOutputStream(const wxPyOutputStream& other)
52 {
53 wxPyThreadBlocker blocker;
54 m_write = other.m_write;
55 m_seek = other.m_seek;
56 m_tell = other.m_tell;
57 m_block = other.m_block;
58 Py_INCREF(m_write);
59 Py_INCREF(m_seek);
60 Py_INCREF(m_tell);
61 }
62
63 protected:
64
65 // implement base class virtuals
66
GetLength() const67 wxFileOffset GetLength() const
68 {
69 wxPyOutputStream* self = (wxPyOutputStream*)this; // cast off const
70 if (m_seek && m_tell) {
71 wxFileOffset temp = self->OnSysTell();
72 wxFileOffset ret = self->OnSysSeek(0, wxFromEnd);
73 self->OnSysSeek(temp, wxFromStart);
74 return ret;
75 }
76 else
77 return wxInvalidOffset;
78 }
79
OnSysRead(void * buffer,size_t bufsize)80 size_t OnSysRead(void *buffer, size_t bufsize)
81 {
82 m_lasterror = wxSTREAM_READ_ERROR;
83 return 0;
84 }
85
OnSysWrite(const void * buffer,size_t bufsize)86 size_t OnSysWrite(const void *buffer, size_t bufsize)
87 {
88 if (bufsize == 0)
89 return 0;
90
91 wxPyThreadBlocker blocker;
92 PyObject* arglist = PyTuple_New(1);
93 PyTuple_SET_ITEM(arglist, 0, PyBytes_FromStringAndSize((char*)buffer, bufsize));
94
95 PyObject* result = PyEval_CallObject(m_write, arglist);
96 Py_DECREF(arglist);
97
98 if (result != NULL)
99 Py_DECREF(result);
100 else
101 m_lasterror = wxSTREAM_WRITE_ERROR;
102 return bufsize;
103 }
104
OnSysSeek(wxFileOffset off,wxSeekMode mode)105 wxFileOffset OnSysSeek(wxFileOffset off, wxSeekMode mode)
106 {
107 wxPyThreadBlocker blocker;
108 PyObject* arglist = PyTuple_New(2);
109
110 if (sizeof(wxFileOffset) > sizeof(long))
111 // wxFileOffset is a 64-bit value...
112 PyTuple_SET_ITEM(arglist, 0, PyLong_FromLongLong(off));
113 else
114 PyTuple_SET_ITEM(arglist, 0, wxPyInt_FromLong(off));
115
116 PyTuple_SET_ITEM(arglist, 1, wxPyInt_FromLong(mode));
117
118
119 PyObject* result = PyEval_CallObject(m_seek, arglist);
120 Py_DECREF(arglist);
121 Py_XDECREF(result);
122 return OnSysTell();
123 }
124
OnSysTell() const125 wxFileOffset OnSysTell() const
126 {
127 wxPyThreadBlocker blocker;
128 PyObject* arglist = Py_BuildValue("()");
129 PyObject* result = PyEval_CallObject(m_tell, arglist);
130 Py_DECREF(arglist);
131 wxFileOffset o = 0;
132 if (result != NULL) {
133 if (PyLong_Check(result))
134 o = PyLong_AsLongLong(result);
135 else
136 o = wxPyInt_AsLong(result);
137 Py_DECREF(result);
138 };
139 return o;
140 }
141
IsSeekable() const142 bool IsSeekable() const
143 {
144 return (m_seek != NULL);
145 }
146
147 private:
148 PyObject* m_write;
149 PyObject* m_seek;
150 PyObject* m_tell;
151 bool m_block;
152 };
153
154 //--------------------------------------------------------------------------
155