Back to index

lightning-sunbird  0.9+nobinonly
PyIInputStream.cpp
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Python XPCOM language bindings.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * ActiveState Tool Corp.
00018  * Portions created by the Initial Developer are Copyright (C) 2000
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *   Mark Hammond <mhammond@skippinet.com.au> (original author)
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 //
00039 // This code is part of the XPCOM extensions for Python.
00040 //
00041 // Written September 2000 by Mark Hammond.
00042 //
00043 // Based heavily on the Python COM support, which is
00044 // (c) Mark Hammond and Greg Stein.
00045 //
00046 // (c) 2000, ActiveState corp.
00047 
00048 #include "PyXPCOM_std.h"
00049 #include "nsIInputStream.h"
00050 
00051 // Prevents us needing to use an nsIScriptableInputStream
00052 // (and even that can't read binary data!!!)
00053 
00054 static nsIInputStream *GetI(PyObject *self) {
00055        nsIID iid = NS_GET_IID(nsIInputStream);
00056 
00057        if (!Py_nsISupports::Check(self, iid)) {
00058               PyErr_SetString(PyExc_TypeError, "This object is not the correct interface");
00059               return NULL;
00060        }
00061        return (nsIInputStream *)Py_nsISupports::GetI(self);
00062 }
00063 
00064 static PyObject *DoPyRead_Buffer(nsIInputStream *pI, PyObject *obBuffer, PRUint32 n)
00065 {
00066        PRUint32 nread;
00067        void *buf;
00068        PRUint32 buf_len;
00069        if (PyObject_AsWriteBuffer(obBuffer, &buf, (int *)&buf_len) != 0) {
00070               PyErr_Clear();
00071               PyErr_SetString(PyExc_TypeError, "The buffer object does not have a write buffer!");
00072               return NULL;
00073        }
00074        if (n==(PRUint32)-1) {
00075               n = buf_len;
00076        } else {
00077               if (n > buf_len) {
00078                      NS_WARNING("Warning: PyIInputStream::read() was passed an integer size greater than the size of the passed buffer!  Buffer size used.\n");
00079                      n = buf_len;
00080               }
00081        }
00082        nsresult r;
00083        Py_BEGIN_ALLOW_THREADS;
00084        r = pI->Read((char *)buf, n, &nread);
00085        Py_END_ALLOW_THREADS;
00086        if ( NS_FAILED(r) )
00087               return PyXPCOM_BuildPyException(r);
00088        return PyInt_FromLong(nread);
00089 }
00090 
00091 static PyObject *DoPyRead_Size(nsIInputStream *pI, PRUint32 n)
00092 {
00093        if (n==(PRUint32)-1) {
00094               nsresult r;
00095               Py_BEGIN_ALLOW_THREADS;
00096               r = pI->Available(&n);
00097               Py_END_ALLOW_THREADS;
00098               if (NS_FAILED(r))
00099                      return PyXPCOM_BuildPyException(r);
00100        }
00101        if (n==0) { // mozilla will assert if we alloc zero bytes.
00102               return PyBuffer_New(0);
00103        }
00104        char *buf = (char *)nsMemory::Alloc(n);
00105        if (buf==NULL) {
00106               PyErr_NoMemory();
00107               return NULL;
00108        }
00109        nsresult r;
00110        PRUint32 nread;
00111        Py_BEGIN_ALLOW_THREADS;
00112        r = pI->Read(buf, n, &nread);
00113        Py_END_ALLOW_THREADS;
00114        PyObject *rc = NULL;
00115        if ( NS_SUCCEEDED(r) ) {
00116               rc = PyBuffer_New(nread);
00117               if (rc != NULL) {
00118                      void *ob_buf;
00119                      PRUint32 buf_len;
00120                      if (PyObject_AsWriteBuffer(rc, &ob_buf, (int *)&buf_len) != 0) {
00121                             // should never fail - we just created it!
00122                             return NULL;
00123                      }
00124                      if (buf_len != nread) {
00125                             PyErr_SetString(PyExc_RuntimeError, "New buffer isnt the size we create it!");
00126                             return NULL;
00127                      }
00128                      memcpy(ob_buf, buf, nread);
00129               }
00130        } else
00131               PyXPCOM_BuildPyException(r);
00132        nsMemory::Free(buf);
00133        return rc;
00134 }
00135 
00136 static PyObject *PyRead(PyObject *self, PyObject *args)
00137 {
00138        PyObject *obBuffer = NULL;
00139        PRUint32 n = (PRUint32)-1;
00140 
00141        nsIInputStream *pI = GetI(self);
00142        if (pI==NULL)
00143               return NULL;
00144        if (PyArg_ParseTuple(args, "|i", (int *)&n))
00145               // This worked - no args, or just an int.
00146               return DoPyRead_Size(pI, n);
00147        // try our other supported arg format.
00148        PyErr_Clear();
00149        if (!PyArg_ParseTuple(args, "O|i", &obBuffer, (int *)&n)) {
00150               PyErr_Clear();
00151               PyErr_SetString(PyExc_TypeError, "'read()' must be called as (buffer_ob, int_size=-1) or (int_size=-1)");
00152               return NULL;
00153        }
00154        return DoPyRead_Buffer(pI, obBuffer, n);
00155 }
00156 
00157 
00158 struct PyMethodDef 
00159 PyMethods_IInputStream[] =
00160 {
00161        { "read", PyRead, 1},
00162        // The rest are handled as normal
00163        {NULL}
00164 };