VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/python/src/PyIInputStream.cpp

Last change on this file was 59809, checked in by vboxsync, 8 years ago

re-applied the remaining changes which were backed out in r105674

  • Property svn:eol-style set to native
File size: 5.6 KB
Line 
1/* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3 *
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
8 *
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
13 *
14 * The Original Code is the Python XPCOM language bindings.
15 *
16 * The Initial Developer of the Original Code is
17 * ActiveState Tool Corp.
18 * Portions created by the Initial Developer are Copyright (C) 2000
19 * the Initial Developer. All Rights Reserved.
20 *
21 * Contributor(s):
22 * Mark Hammond <mhammond@skippinet.com.au> (original author)
23 *
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
35 *
36 * ***** END LICENSE BLOCK ***** */
37
38//
39// This code is part of the XPCOM extensions for Python.
40//
41// Written September 2000 by Mark Hammond.
42//
43// Based heavily on the Python COM support, which is
44// (c) Mark Hammond and Greg Stein.
45//
46// (c) 2000, ActiveState corp.
47
48#include "PyXPCOM_std.h"
49#include "nsIInputStream.h"
50
51// Prevents us needing to use an nsIScriptableInputStream
52// (and even that can't read binary data!!!)
53
54static nsIInputStream *GetI(PyObject *self) {
55 nsIID iid = NS_GET_IID(nsIInputStream);
56
57 if (!Py_nsISupports::Check(self, iid)) {
58 PyErr_SetString(PyExc_TypeError, "This object is not the correct interface");
59 return NULL;
60 }
61 return (nsIInputStream *)Py_nsISupports::GetI(self);
62}
63
64static PyObject *DoPyRead_Buffer(nsIInputStream *pI, PyObject *obBuffer, PRUint32 n)
65{
66 PRUint32 nread;
67 void *buf;
68#ifndef VBOX /* unsafe cast on 64-bit hosts. */
69 PRUint32 buf_len;
70 if (PyObject_AsWriteBuffer(obBuffer, &buf, (Py_ssize_t *)&buf_len) != 0) {
71#else /* VBOX */
72# if PY_VERSION_HEX >= 0x02050000 || defined(PY_SSIZE_T_MIN)
73 Py_ssize_t buf_len;
74# else
75 int buf_len;
76# endif /* VBOX */
77 if (PyObject_AsWriteBuffer(obBuffer, &buf, &buf_len) != 0) {
78#endif
79 PyErr_Clear();
80 PyErr_SetString(PyExc_TypeError, "The buffer object does not have a write buffer!");
81 return NULL;
82 }
83 if (n==(PRUint32)-1) {
84 n = buf_len;
85 } else {
86 if (n > buf_len) {
87 NS_WARNING("Warning: PyIInputStream::read() was passed an integer size greater than the size of the passed buffer! Buffer size used.\n");
88 n = buf_len;
89 }
90 }
91 nsresult r;
92 Py_BEGIN_ALLOW_THREADS;
93 r = pI->Read((char *)buf, n, &nread);
94 Py_END_ALLOW_THREADS;
95 if ( NS_FAILED(r) )
96 return PyXPCOM_BuildPyException(r);
97 return PyInt_FromLong(nread);
98}
99
100static PyObject *DoPyRead_Size(nsIInputStream *pI, PRUint32 n)
101{
102 if (n==(PRUint32)-1) {
103 nsresult r;
104 Py_BEGIN_ALLOW_THREADS;
105 r = pI->Available(&n);
106 Py_END_ALLOW_THREADS;
107 if (NS_FAILED(r))
108 return PyXPCOM_BuildPyException(r);
109 }
110 if (n==0) { // mozilla will assert if we alloc zero bytes.
111#if PY_MAJOR_VERSION <= 2
112 return PyBuffer_New(0);
113#else
114 return PyBytes_FromString("");
115#endif
116 }
117 char *buf = (char *)nsMemory::Alloc(n);
118 if (buf==NULL) {
119 PyErr_NoMemory();
120 return NULL;
121 }
122 nsresult r;
123 PRUint32 nread;
124 Py_BEGIN_ALLOW_THREADS;
125 r = pI->Read(buf, n, &nread);
126 Py_END_ALLOW_THREADS;
127 PyObject *rc = NULL;
128 if ( NS_SUCCEEDED(r) ) {
129#if PY_MAJOR_VERSION <= 2
130 rc = PyBuffer_New(nread);
131 if (rc != NULL) {
132 void *ob_buf;
133#ifndef VBOX /* unsafe cast on 64-bit hosts. */
134 PRUint32 buf_len;
135 if (PyObject_AsWriteBuffer(rc, &ob_buf, (Py_ssize_t *)&buf_len) != 0) {
136#else /* VBOX */
137# if PY_VERSION_HEX >= 0x02050000 || defined(PY_SSIZE_T_MIN)
138 Py_ssize_t buf_len;
139# else
140 int buf_len;
141# endif /* VBOX */
142 if (PyObject_AsWriteBuffer(rc, &ob_buf, &buf_len) != 0) {
143#endif
144 // should never fail - we just created it!
145 return NULL;
146 }
147 if (buf_len != nread) {
148 PyErr_SetString(PyExc_RuntimeError, "New buffer isnt the size we create it!");
149 return NULL;
150 }
151 memcpy(ob_buf, buf, nread);
152 }
153#else
154 rc = PyBytes_FromStringAndSize(buf, nread);
155#endif
156 } else
157 PyXPCOM_BuildPyException(r);
158 nsMemory::Free(buf);
159 return rc;
160}
161
162static PyObject *PyRead(PyObject *self, PyObject *args)
163{
164 PyObject *obBuffer = NULL;
165 PRUint32 n = (PRUint32)-1;
166
167 nsIInputStream *pI = GetI(self);
168 if (pI==NULL)
169 return NULL;
170 if (PyArg_ParseTuple(args, "|i", (int *)&n))
171 // This worked - no args, or just an int.
172 return DoPyRead_Size(pI, n);
173 // try our other supported arg format.
174 PyErr_Clear();
175 if (!PyArg_ParseTuple(args, "O|i", &obBuffer, (int *)&n)) {
176 PyErr_Clear();
177 PyErr_SetString(PyExc_TypeError, "'read()' must be called as (buffer_ob, int_size=-1) or (int_size=-1)");
178 return NULL;
179 }
180 return DoPyRead_Buffer(pI, obBuffer, n);
181}
182
183
184struct PyMethodDef
185PyMethods_IInputStream[] =
186{
187 { "read", PyRead, 1},
188 // The rest are handled as normal
189 {NULL}
190};
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use