VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/python/src/PyIID.cpp@ 98262

Last change on this file since 98262 was 90632, checked in by vboxsync, 4 years ago

xpcom/python: Use PyObject_Init instead of _Py_NewReferences for all versions. bugref:10079

  • Property svn:eol-style set to native
File size: 13.0 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// Py_nsIID.cpp -- IID type for Python/XPCOM
39//
40// This code is part of the XPCOM extensions for Python.
41//
42// Written May 2000 by Mark Hammond.
43//
44// Based heavily on the Python COM support, which is
45// (c) Mark Hammond and Greg Stein.
46//
47// (c) 2000, ActiveState corp.
48//
49// @doc
50
51#include "PyXPCOM_std.h"
52#include <nsIInterfaceInfoManager.h>
53
54nsIID Py_nsIID_NULL = {0,0,0,{0,0,0,0,0,0,0,0}};
55
56// @pymethod <o Py_nsIID>|xpcom|IID|Creates a new IID object
57PYXPCOM_EXPORT PyObject *PyXPCOMMethod_IID(PyObject *self, PyObject *args)
58{
59 PyObject *obIID;
60 PyObject *obBuf;
61 if ( PyArg_ParseTuple(args, "O", &obBuf)) {
62#if PY_MAJOR_VERSION <= 2
63 if (PyBuffer_Check(obBuf)) {
64 PyBufferProcs *pb = NULL;
65 pb = obBuf->ob_type->tp_as_buffer;
66 void *buf = NULL;
67 int size = (*pb->bf_getreadbuffer)(obBuf, 0, &buf);
68#else
69 if (PyObject_CheckBuffer(obBuf)) {
70# ifndef Py_LIMITED_API
71 Py_buffer view;
72 if (PyObject_GetBuffer(obBuf, &view, PyBUF_CONTIG_RO) != 0) {
73 PyErr_Format(PyExc_ValueError, "Could not get contiguous buffer from object");
74 return NULL;
75 }
76 Py_ssize_t size = view.len;
77 const void *buf = view.buf;
78# else /* Py_LIMITED_API - the buffer API is non-existant, from what I can tell */
79 const void *buf = NULL;
80 Py_ssize_t size = 0;
81 if (PyObject_AsReadBuffer(obBuf, &buf, &size) != 0) {
82 PyErr_Format(PyExc_ValueError, "Could not get read-only buffer from object");
83 return NULL;
84 }
85# endif /* Py_LIMITED_API */
86#endif
87 if (size != sizeof(nsIID) || buf==NULL) {
88#if PY_MAJOR_VERSION >= 3 && !defined(Py_LIMITED_API)
89 PyBuffer_Release(&view);
90#endif
91#ifdef VBOX
92 PyErr_Format(PyExc_ValueError, "A buffer object to be converted to an IID must be exactly %d bytes long", (int)sizeof(nsIID));
93#else
94 PyErr_Format(PyExc_ValueError, "A buffer object to be converted to an IID must be exactly %d bytes long", sizeof(nsIID));
95#endif
96 return NULL;
97 }
98 nsIID iid;
99 unsigned char const *ptr = (unsigned char const *)buf;
100 iid.m0 = XPT_SWAB32(*((PRUint32 *)ptr));
101 ptr = ((unsigned char const *)buf) + offsetof(nsIID, m1);
102 iid.m1 = XPT_SWAB16(*((PRUint16 *)ptr));
103 ptr = ((unsigned char const *)buf) + offsetof(nsIID, m2);
104 iid.m2 = XPT_SWAB16(*((PRUint16 *)ptr));
105 ptr = ((unsigned char const *)buf) + offsetof(nsIID, m3);
106 for (int i=0;i<8;i++) {
107 iid.m3[i] = *((PRUint8 const *)ptr);
108 ptr += sizeof(PRUint8);
109 }
110#if PY_MAJOR_VERSION >= 3 && !defined(Py_LIMITED_API)
111 PyBuffer_Release(&view);
112#endif
113 return new Py_nsIID(iid);
114 }
115 }
116 PyErr_Clear();
117 // @pyparm string/Unicode|iidString||A string representation of an IID, or a ContractID.
118 if ( !PyArg_ParseTuple(args, "O", &obIID) )
119 return NULL;
120
121 nsIID iid;
122 if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
123 return NULL;
124 return new Py_nsIID(iid);
125}
126
127/*static*/ PRBool
128Py_nsIID::IIDFromPyObject(PyObject *ob, nsIID *pRet) {
129 PRBool ok = PR_TRUE;
130 nsIID iid;
131 if (ob==NULL) {
132 PyErr_SetString(PyExc_RuntimeError, "The IID object is invalid!");
133 return PR_FALSE;
134 }
135#if PY_MAJOR_VERSION <= 2
136 if (PyString_Check(ob)) {
137 ok = iid.Parse(PyString_AsString(ob));
138#else
139 if (PyUnicode_Check(ob)) {
140 ok = iid.Parse(PyUnicode_AsUTF8(ob));
141#endif
142 if (!ok) {
143 PyXPCOM_BuildPyException(NS_ERROR_ILLEGAL_VALUE);
144 return PR_FALSE;
145 }
146#ifndef Py_LIMITED_API
147 } else if (ob->ob_type == &type) {
148#else
149 } else if (ob->ob_type == Py_nsIID::GetTypeObject()) {
150#endif
151 iid = ((Py_nsIID *)ob)->m_iid;
152 } else if (PyObject_HasAttrString(ob, "__class__")) {
153 // Get the _iidobj_ attribute
154 PyObject *use_ob = PyObject_GetAttrString(ob, "_iidobj_");
155 if (use_ob==NULL) {
156 PyErr_SetString(PyExc_TypeError, "Only instances with _iidobj_ attributes can be used as IID objects");
157 return PR_FALSE;
158 }
159#ifndef Py_LIMITED_API
160 if (use_ob->ob_type != &type) {
161#else
162 if (use_ob->ob_type != Py_nsIID::GetTypeObject()) {
163#endif
164 Py_DECREF(use_ob);
165 PyErr_SetString(PyExc_TypeError, "instance _iidobj_ attributes must be raw IID object");
166 return PR_FALSE;
167 }
168 iid = ((Py_nsIID *)use_ob)->m_iid;
169 Py_DECREF(use_ob);
170 } else {
171 PyErr_Format(PyExc_TypeError, "Objects of type '%s' can not be converted to an IID", PyXPCOM_ObTypeName(ob));
172 ok = PR_FALSE;
173 }
174 if (ok) *pRet = iid;
175 return ok;
176}
177
178
179// @object Py_nsIID|A Python object, representing an IID/CLSID.
180// <nl>All pythoncom functions that return a CLSID/IID will return one of these
181// objects. However, in almost all cases, functions that expect a CLSID/IID
182// as a param will accept either a string object, or a native Py_nsIID object.
183#ifndef Py_LIMITED_API
184PyTypeObject Py_nsIID::type =
185{
186 PyVarObject_HEAD_INIT(&PyType_Type, 0)
187 "IID",
188 sizeof(Py_nsIID),
189 0,
190 PyTypeMethod_dealloc, /* tp_dealloc */
191 0, /* tp_print */
192 PyTypeMethod_getattr, /* tp_getattr */
193 0, /* tp_setattr */
194#if PY_MAJOR_VERSION <= 2
195 PyTypeMethod_compare, /* tp_compare */
196#else
197 0, /* reserved */
198#endif
199 PyTypeMethod_repr, /* tp_repr */
200 0, /* tp_as_number */
201 0, /* tp_as_sequence */
202 0, /* tp_as_mapping */
203 PyTypeMethod_hash, /* tp_hash */
204 0, /* tp_call */
205 PyTypeMethod_str, /* tp_str */
206 0, /* tp_getattro */
207 0, /* tp_setattro */
208 0, /* tp_as_buffer */
209 0, /* tp_flags */
210 0, /* tp_doc */
211 0, /* tp_traverse */
212 0, /* tp_clear */
213 PyTypeMethod_richcompare, /* tp_richcompare */
214 0, /* tp_weaklistoffset */
215 0, /* tp_iter */
216 0, /* tp_iternext */
217 0, /* tp_methods */
218 0, /* tp_members */
219 0, /* tp_getset */
220 0, /* tp_base */
221};
222#else /* Py_LIMITED_API */
223NS_EXPORT_STATIC_MEMBER_(PyTypeObject *) Py_nsIID::s_pType = NULL;
224
225PyTypeObject *Py_nsIID::GetTypeObject(void)
226{
227 PyTypeObject *pTypeObj = Py_nsIID::s_pType;
228 if (pTypeObj)
229 return pTypeObj;
230
231 PyType_Slot aTypeSlots[] = {
232 { Py_tp_base, &PyType_Type },
233 { Py_tp_dealloc, (void *)(uintptr_t)&Py_nsIID::PyTypeMethod_dealloc },
234 { Py_tp_getattr, (void *)(uintptr_t)&Py_nsIID::PyTypeMethod_getattr },
235 { Py_tp_repr, (void *)(uintptr_t)&Py_nsIID::PyTypeMethod_repr },
236 { Py_tp_hash, (void *)(uintptr_t)&Py_nsIID::PyTypeMethod_hash },
237 { Py_tp_str, (void *)(uintptr_t)&Py_nsIID::PyTypeMethod_str },
238 { Py_tp_richcompare, (void *)(uintptr_t)&Py_nsIID::PyTypeMethod_richcompare },
239 { 0, NULL } /* terminator */
240 };
241 PyType_Spec TypeSpec = {
242 /* .name: */ "IID",
243 /* .basicsize: */ sizeof(Py_nsIID),
244 /* .itemsize: */ 0,
245 /* .flags: */ 0,
246 /* .slots: */ aTypeSlots,
247 };
248
249 PyObject *exc_typ = NULL, *exc_val = NULL, *exc_tb = NULL;
250 PyErr_Fetch(&exc_typ, &exc_val, &exc_tb); /* goes south in PyType_Ready if we don't clear exceptions first. */
251
252 pTypeObj = (PyTypeObject *)PyType_FromSpec(&TypeSpec);
253 assert(pTypeObj);
254
255 PyErr_Restore(exc_typ, exc_val, exc_tb);
256 Py_nsIID::s_pType = pTypeObj;
257 return pTypeObj;
258}
259#endif /* Py_LIMITED_API */
260
261Py_nsIID::Py_nsIID(const nsIID &riid)
262{
263#ifndef Py_LIMITED_API
264 ob_type = &type;
265#else
266 ob_type = GetTypeObject();
267#endif
268#if 1 /* VBox: Must use for 3.9+, includes _Py_NewReferences. Works for all older versions too. @bugref{10079} */
269 PyObject_Init(this, ob_type);
270#else
271 _Py_NewReference(this);
272#endif
273
274 m_iid = riid;
275}
276
277/*static*/PyObject *
278Py_nsIID::PyTypeMethod_getattr(PyObject *self, char *name)
279{
280 Py_nsIID *me = (Py_nsIID *)self;
281 if (strcmp(name, "name")==0) {
282 char *iid_repr = nsnull;
283 nsCOMPtr<nsIInterfaceInfoManager> iim(do_GetService(
284 NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID));
285 if (iim!=nsnull)
286 iim->GetNameForIID(&me->m_iid, &iid_repr);
287 if (iid_repr==nsnull)
288 iid_repr = me->m_iid.ToString();
289 PyObject *ret;
290 if (iid_repr != nsnull) {
291#if PY_MAJOR_VERSION <= 2
292 ret = PyString_FromString(iid_repr);
293#else
294 ret = PyUnicode_FromString(iid_repr);
295#endif
296 nsMemory::Free(iid_repr);
297 } else
298#if PY_MAJOR_VERSION <= 2
299 ret = PyString_FromString("<cant get IID info!>");
300#else
301 ret = PyUnicode_FromString("<cant get IID info!>");
302#endif
303 return ret;
304 }
305 return PyErr_Format(PyExc_AttributeError, "IID objects have no attribute '%s'", name);
306}
307
308#if PY_MAJOR_VERSION <= 2
309/* static */ int
310Py_nsIID::PyTypeMethod_compare(PyObject *self, PyObject *other)
311{
312 Py_nsIID *s_iid = (Py_nsIID *)self;
313 Py_nsIID *o_iid = (Py_nsIID *)other;
314 int rc = memcmp(&s_iid->m_iid, &o_iid->m_iid, sizeof(s_iid->m_iid));
315 return rc == 0 ? 0 : (rc < 0 ? -1 : 1);
316}
317#endif
318
319/* static */ PyObject *
320Py_nsIID::PyTypeMethod_richcompare(PyObject *self, PyObject *other, int op)
321{
322 PyObject *result = NULL;
323 Py_nsIID *s_iid = (Py_nsIID *)self;
324 Py_nsIID *o_iid = (Py_nsIID *)other;
325 int rc = memcmp(&s_iid->m_iid, &o_iid->m_iid, sizeof(s_iid->m_iid));
326 switch (op)
327 {
328 case Py_LT:
329 result = rc < 0 ? Py_True : Py_False;
330 break;
331 case Py_LE:
332 result = rc <= 0 ? Py_True : Py_False;
333 break;
334 case Py_EQ:
335 result = rc == 0 ? Py_True : Py_False;
336 break;
337 case Py_NE:
338 result = rc != 0 ? Py_True : Py_False;
339 break;
340 case Py_GT:
341 result = rc > 0 ? Py_True : Py_False;
342 break;
343 case Py_GE:
344 result = rc >= 0 ? Py_True : Py_False;
345 break;
346 }
347 Py_XINCREF(result);
348 return result;
349}
350
351/* static */ PyObject *
352Py_nsIID::PyTypeMethod_repr(PyObject *self)
353{
354 Py_nsIID *s_iid = (Py_nsIID *)self;
355 char buf[256];
356 char *sziid = s_iid->m_iid.ToString();
357#ifdef VBOX
358 snprintf(buf, sizeof(buf), "_xpcom.ID('%s')", sziid);
359#else
360 sprintf(buf, "_xpcom.IID('%s')", sziid);
361#endif
362 nsMemory::Free(sziid);
363#if PY_MAJOR_VERSION <= 2
364 return PyString_FromString(buf);
365#else
366 return PyUnicode_FromString(buf);
367#endif
368}
369
370/* static */ PyObject *
371Py_nsIID::PyTypeMethod_str(PyObject *self)
372{
373 Py_nsIID *s_iid = (Py_nsIID *)self;
374 char *sziid = s_iid->m_iid.ToString();
375#if PY_MAJOR_VERSION <= 2
376 PyObject *ret = PyString_FromString(sziid);
377#else
378 PyObject *ret = PyUnicode_FromString(sziid);
379#endif
380 nsMemory::Free(sziid);
381 return ret;
382}
383
384#if PY_VERSION_HEX >= 0x03020000
385/* static */Py_hash_t
386Py_nsIID::PyTypeMethod_hash(PyObject *self)
387#else
388/* static */long
389Py_nsIID::PyTypeMethod_hash(PyObject *self)
390#endif
391{
392 const nsIID &iid = ((Py_nsIID *)self)->m_iid;
393
394#if PY_VERSION_HEX >= 0x03020000
395 Py_hash_t ret = iid.m0 + iid.m1 + iid.m2;
396#else
397 long ret = iid.m0 + iid.m1 + iid.m2;
398#endif
399 for (int i=0;i<7;i++)
400 ret += iid.m3[i];
401 if ( ret == -1 )
402 return -2;
403 return ret;
404}
405
406/*static*/ void
407Py_nsIID::PyTypeMethod_dealloc(PyObject *ob)
408{
409 delete (Py_nsIID *)ob;
410}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette