VirtualBox

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

Last change on this file was 103125, checked in by vboxsync, 4 months ago

libs/xpcom/python: comment typo

  • Property svn:eol-style set to native
File size: 13.5 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 { Py_tp_is_gc, (void *)(uintptr_t)&Py_nsIID::PyTypeMethod_is_gc },
240 { 0, NULL } /* terminator */
241 };
242 PyType_Spec TypeSpec = {
243 /* .name: */ "IID",
244 /* .basicsize: */ sizeof(Py_nsIID),
245 /* .itemsize: */ 0,
246 /* .flags: */ Py_TPFLAGS_DEFAULT,
247 /* .slots: */ aTypeSlots,
248 };
249
250 PyObject *exc_typ = NULL, *exc_val = NULL, *exc_tb = NULL;
251 PyErr_Fetch(&exc_typ, &exc_val, &exc_tb); /* goes south in PyType_Ready if we don't clear exceptions first. */
252
253 pTypeObj = (PyTypeObject *)PyType_FromSpec(&TypeSpec);
254 assert(pTypeObj);
255
256 PyErr_Restore(exc_typ, exc_val, exc_tb);
257 Py_nsIID::s_pType = pTypeObj;
258 return pTypeObj;
259}
260#endif /* Py_LIMITED_API */
261
262Py_nsIID::Py_nsIID(const nsIID &riid)
263{
264#ifndef Py_LIMITED_API
265 ob_type = &type;
266#else
267 ob_type = GetTypeObject();
268#endif
269#if 1 /* VBox: Must use for 3.9+, includes _Py_NewReferences. Works for all older versions too. @bugref{10079} */
270 PyObject_Init(this, ob_type);
271#else
272 _Py_NewReference(this);
273#endif
274
275 m_iid = riid;
276}
277
278/*static*/PyObject *
279Py_nsIID::PyTypeMethod_getattr(PyObject *self, char *name)
280{
281 Py_nsIID *me = (Py_nsIID *)self;
282 if (strcmp(name, "name")==0) {
283 char *iid_repr = nsnull;
284 nsCOMPtr<nsIInterfaceInfoManager> iim(do_GetService(
285 NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID));
286 if (iim!=nsnull)
287 iim->GetNameForIID(&me->m_iid, &iid_repr);
288 if (iid_repr==nsnull)
289 iid_repr = me->m_iid.ToString();
290 PyObject *ret;
291 if (iid_repr != nsnull) {
292#if PY_MAJOR_VERSION <= 2
293 ret = PyString_FromString(iid_repr);
294#else
295 ret = PyUnicode_FromString(iid_repr);
296#endif
297 nsMemory::Free(iid_repr);
298 } else
299#if PY_MAJOR_VERSION <= 2
300 ret = PyString_FromString("<cant get IID info!>");
301#else
302 ret = PyUnicode_FromString("<cant get IID info!>");
303#endif
304 return ret;
305 }
306 return PyErr_Format(PyExc_AttributeError, "IID objects have no attribute '%s'", name);
307}
308
309#if PY_MAJOR_VERSION <= 2
310/* static */ int
311Py_nsIID::PyTypeMethod_compare(PyObject *self, PyObject *other)
312{
313 Py_nsIID *s_iid = (Py_nsIID *)self;
314 Py_nsIID *o_iid = (Py_nsIID *)other;
315 int rc = memcmp(&s_iid->m_iid, &o_iid->m_iid, sizeof(s_iid->m_iid));
316 return rc == 0 ? 0 : (rc < 0 ? -1 : 1);
317}
318#endif
319
320/* static */ PyObject *
321Py_nsIID::PyTypeMethod_richcompare(PyObject *self, PyObject *other, int op)
322{
323 nsIID iid;
324 if (!Py_nsIID::IIDFromPyObject(other, &iid))
325 {
326 /* Can't do comparison besides equality/inequality if the other object does not contain an IID. */
327 if (op == Py_EQ)
328 Py_RETURN_FALSE;
329 else if (op == Py_NE)
330 Py_RETURN_TRUE;
331
332 PyErr_SetString(PyExc_TypeError, "Comparison between different object types is not defined");
333 return NULL;
334 }
335
336 PyObject *result = NULL;
337 Py_nsIID *s_iid = (Py_nsIID *)self;
338 int rc = memcmp(&s_iid->m_iid, &iid, sizeof(s_iid->m_iid));
339 switch (op)
340 {
341 case Py_LT:
342 result = rc < 0 ? Py_True : Py_False;
343 break;
344 case Py_LE:
345 result = rc <= 0 ? Py_True : Py_False;
346 break;
347 case Py_EQ:
348 result = rc == 0 ? Py_True : Py_False;
349 break;
350 case Py_NE:
351 result = rc != 0 ? Py_True : Py_False;
352 break;
353 case Py_GT:
354 result = rc > 0 ? Py_True : Py_False;
355 break;
356 case Py_GE:
357 result = rc >= 0 ? Py_True : Py_False;
358 break;
359 }
360 Py_XINCREF(result);
361 return result;
362}
363
364/* static */ PyObject *
365Py_nsIID::PyTypeMethod_repr(PyObject *self)
366{
367 Py_nsIID *s_iid = (Py_nsIID *)self;
368 char buf[256];
369 char *sziid = s_iid->m_iid.ToString();
370#ifdef VBOX
371 snprintf(buf, sizeof(buf), "_xpcom.ID('%s')", sziid);
372#else
373 sprintf(buf, "_xpcom.IID('%s')", sziid);
374#endif
375 nsMemory::Free(sziid);
376#if PY_MAJOR_VERSION <= 2
377 return PyString_FromString(buf);
378#else
379 return PyUnicode_FromString(buf);
380#endif
381}
382
383/* static */ PyObject *
384Py_nsIID::PyTypeMethod_str(PyObject *self)
385{
386 Py_nsIID *s_iid = (Py_nsIID *)self;
387 char *sziid = s_iid->m_iid.ToString();
388#if PY_MAJOR_VERSION <= 2
389 PyObject *ret = PyString_FromString(sziid);
390#else
391 PyObject *ret = PyUnicode_FromString(sziid);
392#endif
393 nsMemory::Free(sziid);
394 return ret;
395}
396
397#if PY_VERSION_HEX >= 0x03020000
398/* static */Py_hash_t
399Py_nsIID::PyTypeMethod_hash(PyObject *self)
400#else
401/* static */long
402Py_nsIID::PyTypeMethod_hash(PyObject *self)
403#endif
404{
405 const nsIID &iid = ((Py_nsIID *)self)->m_iid;
406
407#if PY_VERSION_HEX >= 0x03020000
408 Py_hash_t ret = iid.m0 + iid.m1 + iid.m2;
409#else
410 long ret = iid.m0 + iid.m1 + iid.m2;
411#endif
412 for (int i=0;i<7;i++)
413 ret += iid.m3[i];
414 if ( ret == -1 )
415 return -2;
416 return ret;
417}
418
419/*static*/ void
420Py_nsIID::PyTypeMethod_dealloc(PyObject *ob)
421{
422 delete (Py_nsIID *)ob;
423}
424
425#ifdef Py_LIMITED_API
426/* static */ int
427Py_nsIID::PyTypeMethod_is_gc(PyObject *self)
428{
429 return 0;
430}
431#endif
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use