+// wxPyInputStream and wxPyCBInputStream methods
+
+
+void wxPyInputStream::close() {
+ /* do nothing for now */
+}
+
+void wxPyInputStream::flush() {
+ /* do nothing for now */
+}
+
+bool wxPyInputStream::eof() {
+ if (m_wxis)
+ return m_wxis->Eof();
+ else
+ return TRUE;
+}
+
+wxPyInputStream::~wxPyInputStream() {
+ /* do nothing */
+}
+
+
+
+
+PyObject* wxPyInputStream::read(int size) {
+ PyObject* obj = NULL;
+ wxMemoryBuffer buf;
+ const int BUFSIZE = 1024;
+
+ // check if we have a real wxInputStream to work with
+ if (!m_wxis) {
+ PyErr_SetString(PyExc_IOError, "no valid C-wxInputStream");
+ return NULL;
+ }
+
+ if (size < 0) {
+ // read until EOF
+ while (! m_wxis->Eof()) {
+ m_wxis->Read(buf.GetAppendBuf(BUFSIZE), BUFSIZE);
+ buf.UngetAppendBuf(m_wxis->LastRead());
+ }
+
+ } else { // Read only size number of characters
+ m_wxis->Read(buf.GetWriteBuf(size), size);
+ buf.UngetWriteBuf(m_wxis->LastRead());
+ }
+
+ // error check
+ if (m_wxis->LastError() == wxSTREAM_READ_ERROR) {
+ PyErr_SetString(PyExc_IOError,"IOError in wxInputStream");
+ }
+ else {
+ // We use only strings for the streams, not unicode
+ obj = PyString_FromStringAndSize(buf, buf.GetDataLen());
+ }
+ return obj;
+}
+
+
+PyObject* wxPyInputStream::readline(int size) {
+ PyObject* obj = NULL;
+ wxMemoryBuffer buf;
+ int i;
+ char ch;
+
+ // check if we have a real wxInputStream to work with
+ if (!m_wxis) {
+ PyErr_SetString(PyExc_IOError,"no valid C-wxInputStream");
+ return NULL;
+ }
+
+ // read until \n or byte limit reached
+ for (i=ch=0; (ch != '\n') && (!m_wxis->Eof()) && ((size < 0) || (i < size)); i++) {
+ ch = m_wxis->GetC();
+ buf.AppendByte(ch);
+ }
+
+ // errorcheck
+ if (m_wxis->LastError() == wxSTREAM_READ_ERROR) {
+ PyErr_SetString(PyExc_IOError,"IOError in wxInputStream");
+ }
+ else {
+ // We use only strings for the streams, not unicode
+ obj = PyString_FromStringAndSize((char*)buf.GetData(), buf.GetDataLen());
+ }
+ return obj;
+}
+
+
+PyObject* wxPyInputStream::readlines(int sizehint) {
+ PyObject* pylist;
+
+ // check if we have a real wxInputStream to work with
+ if (!m_wxis) {
+ PyErr_SetString(PyExc_IOError,"no valid C-wxInputStream below");
+ return NULL;
+ }
+
+ // init list
+ pylist = PyList_New(0);
+ if (!pylist) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ // read sizehint bytes or until EOF
+ int i;
+ for (i=0; (!m_wxis->Eof()) && ((sizehint < 0) || (i < sizehint));) {
+ PyObject* s = this->readline();
+ if (s == NULL) {
+ Py_DECREF(pylist);
+ return NULL;
+ }
+ PyList_Append(pylist, s);
+ i += PyString_Size(s);
+ }
+
+ // error check
+ if (m_wxis->LastError() == wxSTREAM_READ_ERROR) {
+ Py_DECREF(pylist);
+ PyErr_SetString(PyExc_IOError,"IOError in wxInputStream");
+ return NULL;
+ }
+
+ return pylist;
+}
+
+
+void wxPyInputStream::seek(int offset, int whence) {
+ if (m_wxis)
+ m_wxis->SeekI(offset, wxSeekMode(whence));
+}
+
+int wxPyInputStream::tell(){
+ if (m_wxis)
+ return m_wxis->TellI();
+ else return 0;
+}
+
+
+
+
+wxPyCBInputStream::wxPyCBInputStream(PyObject *r, PyObject *s, PyObject *t, bool block)
+ : wxInputStream(), m_read(r), m_seek(s), m_tell(t), m_block(block)
+{}
+
+
+wxPyCBInputStream::~wxPyCBInputStream() {
+ if (m_block) wxPyBeginBlockThreads();
+ Py_XDECREF(m_read);
+ Py_XDECREF(m_seek);
+ Py_XDECREF(m_tell);
+ if (m_block) wxPyEndBlockThreads();
+}
+
+
+wxPyCBInputStream* wxPyCBInputStream::create(PyObject *py, bool block) {
+ if (block) wxPyBeginBlockThreads();
+
+ PyObject* read = getMethod(py, "read");
+ PyObject* seek = getMethod(py, "seek");
+ PyObject* tell = getMethod(py, "tell");
+
+ if (!read) {
+ PyErr_SetString(PyExc_TypeError, "Not a file-like object");
+ Py_XDECREF(read);
+ Py_XDECREF(seek);
+ Py_XDECREF(tell);
+ if (block) wxPyEndBlockThreads();
+ return NULL;
+ }
+
+ if (block) wxPyEndBlockThreads();
+ return new wxPyCBInputStream(read, seek, tell, block);
+}
+
+
+wxPyCBInputStream* wxPyCBInputStream_create(PyObject *py, bool block) {
+ return wxPyCBInputStream::create(py, block);
+}
+
+PyObject* wxPyCBInputStream::getMethod(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;
+}
+
+
+size_t wxPyCBInputStream::GetSize() const {
+ wxPyCBInputStream* self = (wxPyCBInputStream*)this; // cast off const
+ if (m_seek && m_tell) {
+ off_t temp = self->OnSysTell();
+ off_t ret = self->OnSysSeek(0, wxFromEnd);
+ self->OnSysSeek(temp, wxFromStart);
+ return ret;
+ }
+ else
+ return 0;
+}
+
+
+size_t wxPyCBInputStream::OnSysRead(void *buffer, size_t bufsize) {
+ if (bufsize == 0)
+ return 0;
+
+ wxPyBeginBlockThreads();
+ PyObject* arglist = Py_BuildValue("(i)", bufsize);
+ PyObject* result = PyEval_CallObject(m_read, arglist);
+ Py_DECREF(arglist);
+
+ size_t o = 0;
+ if ((result != NULL) && PyString_Check(result)) {
+ o = PyString_Size(result);
+ if (o == 0)
+ m_lasterror = wxSTREAM_EOF;
+ if (o > bufsize)
+ o = bufsize;
+ memcpy((char*)buffer, PyString_AsString(result), o); // strings only, not unicode...
+ Py_DECREF(result);
+
+ }
+ else
+ m_lasterror = wxSTREAM_READ_ERROR;
+ wxPyEndBlockThreads();
+ m_lastcount = o;
+ return o;
+}
+
+size_t wxPyCBInputStream::OnSysWrite(const void *buffer, size_t bufsize) {
+ m_lasterror = wxSTREAM_WRITE_ERROR;
+ return 0;
+}
+
+off_t wxPyCBInputStream::OnSysSeek(off_t off, wxSeekMode mode) {
+ wxPyBeginBlockThreads();
+ PyObject* arglist = Py_BuildValue("(ii)", off, mode);
+ PyObject* result = PyEval_CallObject(m_seek, arglist);
+ Py_DECREF(arglist);
+ Py_XDECREF(result);
+ wxPyEndBlockThreads();
+ return OnSysTell();
+}
+
+off_t wxPyCBInputStream::OnSysTell() const {
+ wxPyBeginBlockThreads();
+ PyObject* arglist = Py_BuildValue("()");
+ PyObject* result = PyEval_CallObject(m_tell, arglist);
+ Py_DECREF(arglist);
+ off_t o = 0;
+ if (result != NULL) {
+ o = PyInt_AsLong(result);
+ Py_DECREF(result);
+ };
+ wxPyEndBlockThreads();
+ return o;
+}
+
+//----------------------------------------------------------------------