Back to index

lightning-sunbird  0.9+nobinonly
PyIID.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 // Py_nsIID.cpp -- IID type for Python/XPCOM
00039 //
00040 // This code is part of the XPCOM extensions for Python.
00041 //
00042 // Written May 2000 by Mark Hammond.
00043 //
00044 // Based heavily on the Python COM support, which is
00045 // (c) Mark Hammond and Greg Stein.
00046 //
00047 // (c) 2000, ActiveState corp.
00048 //
00049 // @doc
00050 
00051 #include "PyXPCOM_std.h"
00052 #include <nsIInterfaceInfoManager.h>
00053 
00054 nsIID Py_nsIID_NULL = {0,0,0,{0,0,0,0,0,0,0,0}};
00055 
00056 // @pymethod <o Py_nsIID>|xpcom|IID|Creates a new IID object
00057 PyObject *PyXPCOMMethod_IID(PyObject *self, PyObject *args)
00058 {
00059        PyObject *obIID;
00060        PyObject *obBuf;
00061        if ( PyArg_ParseTuple(args, "O", &obBuf)) {
00062               if (PyBuffer_Check(obBuf)) {
00063                      PyBufferProcs *pb = NULL;
00064                      pb = obBuf->ob_type->tp_as_buffer;
00065                      void *buf = NULL;
00066                      int size = (*pb->bf_getreadbuffer)(obBuf, 0, &buf);
00067                      if (size != sizeof(nsIID) || buf==NULL) {
00068                             PyErr_Format(PyExc_ValueError, "A buffer object to be converted to an IID must be exactly %d bytes long", sizeof(nsIID));
00069                             return NULL;
00070                      }
00071                      nsIID iid;
00072                      unsigned char *ptr = (unsigned char *)buf;
00073                      iid.m0 = XPT_SWAB32(*((PRUint32 *)ptr));
00074                      ptr = ((unsigned char *)buf) + offsetof(nsIID, m1);
00075                      iid.m1 = XPT_SWAB16(*((PRUint16 *)ptr));
00076                      ptr = ((unsigned char *)buf) + offsetof(nsIID, m2);
00077                      iid.m2 = XPT_SWAB16(*((PRUint16 *)ptr));
00078                      ptr = ((unsigned char *)buf) + offsetof(nsIID, m3);
00079                      for (int i=0;i<8;i++) {
00080                             iid.m3[i] = *((PRUint8 *)ptr);
00081                             ptr += sizeof(PRUint8);
00082                      }
00083                      return new Py_nsIID(iid);
00084               }
00085        }
00086        PyErr_Clear();
00087        // @pyparm string/Unicode|iidString||A string representation of an IID, or a ContractID.
00088        if ( !PyArg_ParseTuple(args, "O", &obIID) )
00089               return NULL;
00090 
00091        nsIID iid;
00092        if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
00093               return NULL;
00094        return new Py_nsIID(iid);
00095 }
00096 
00097 /*static*/ PRBool
00098 Py_nsIID::IIDFromPyObject(PyObject *ob, nsIID *pRet) {
00099        PRBool ok = PR_TRUE;
00100        nsIID iid;
00101        if (ob==NULL) {
00102               PyErr_SetString(PyExc_RuntimeError, "The IID object is invalid!");
00103               return PR_FALSE;
00104        }
00105        if (PyString_Check(ob)) {
00106               ok = iid.Parse(PyString_AsString(ob));
00107               if (!ok) {
00108                      PyXPCOM_BuildPyException(NS_ERROR_ILLEGAL_VALUE);
00109                      return PR_FALSE;
00110               }
00111        } else if (ob->ob_type == &type) {
00112               iid = ((Py_nsIID *)ob)->m_iid;
00113        } else if (PyInstance_Check(ob)) {
00114               // Get the _iidobj_ attribute
00115               PyObject *use_ob = PyObject_GetAttrString(ob, "_iidobj_");
00116               if (use_ob==NULL) {
00117                      PyErr_SetString(PyExc_TypeError, "Only instances with _iidobj_ attributes can be used as IID objects");
00118                      return PR_FALSE;
00119               }
00120               if (use_ob->ob_type != &type) {
00121                      Py_DECREF(use_ob);
00122                      PyErr_SetString(PyExc_TypeError, "instance _iidobj_ attributes must be raw IID object");
00123                      return PR_FALSE;
00124               }
00125               iid = ((Py_nsIID *)use_ob)->m_iid;
00126               Py_DECREF(use_ob);
00127        } else {
00128               PyErr_Format(PyExc_TypeError, "Objects of type '%s' can not be converted to an IID", ob->ob_type->tp_name);
00129               ok = PR_FALSE;
00130        }
00131        if (ok) *pRet = iid;
00132        return ok;
00133 }
00134 
00135 
00136 // @object Py_nsIID|A Python object, representing an IID/CLSID.
00137 // <nl>All pythoncom functions that return a CLSID/IID will return one of these
00138 // objects.  However, in almost all cases, functions that expect a CLSID/IID
00139 // as a param will accept either a string object, or a native Py_nsIID object.
00140 PyTypeObject Py_nsIID::type =
00141 {
00142        PyObject_HEAD_INIT(&PyType_Type)
00143        0,
00144        "IID",
00145        sizeof(Py_nsIID),
00146        0,
00147        PyTypeMethod_dealloc,                           /* tp_dealloc */
00148        0,                                              /* tp_print */
00149        PyTypeMethod_getattr,                           /* tp_getattr */
00150        0,                                              /* tp_setattr */
00151        PyTypeMethod_compare,                           /* tp_compare */
00152        PyTypeMethod_repr,                              /* tp_repr */
00153        0,                                              /* tp_as_number */
00154        0,                                              /* tp_as_sequence */
00155        0,                                              /* tp_as_mapping */
00156        PyTypeMethod_hash,                              /* tp_hash */
00157        0,                                              /* tp_call */
00158        PyTypeMethod_str,                               /* tp_str */
00159 };
00160 
00161 Py_nsIID::Py_nsIID(const nsIID &riid)
00162 {
00163        ob_type = &type;
00164        _Py_NewReference(this);
00165        m_iid = riid;
00166 }
00167 
00168 /*static*/PyObject *
00169 Py_nsIID::PyTypeMethod_getattr(PyObject *self, char *name)
00170 {
00171        Py_nsIID *me = (Py_nsIID *)self;
00172        if (strcmp(name, "name")==0) {
00173               char *iid_repr = nsnull;
00174               nsCOMPtr<nsIInterfaceInfoManager> iim = XPTI_GetInterfaceInfoManager();
00175               if (iim!=nsnull)
00176                      iim->GetNameForIID(&me->m_iid, &iid_repr);
00177               if (iid_repr==nsnull)
00178                      iid_repr = me->m_iid.ToString();
00179               PyObject *ret;
00180               if (iid_repr != nsnull) {
00181                      ret = PyString_FromString(iid_repr);
00182                      nsMemory::Free(iid_repr);
00183               } else
00184                      ret = PyString_FromString("<cant get IID info!>");
00185               return ret;
00186        }
00187        return PyErr_Format(PyExc_AttributeError, "IID objects have no attribute '%s'", name);
00188 }
00189 
00190 /* static */ int
00191 Py_nsIID::PyTypeMethod_compare(PyObject *self, PyObject *other)
00192 {
00193        Py_nsIID *s_iid = (Py_nsIID *)self;
00194        Py_nsIID *o_iid = (Py_nsIID *)other;
00195        int rc = memcmp(&s_iid->m_iid, &o_iid->m_iid, sizeof(s_iid->m_iid)); 
00196        return rc == 0 ? 0 : (rc < 0 ? -1 : 1);
00197 }
00198 
00199 /* static */ PyObject *
00200 Py_nsIID::PyTypeMethod_repr(PyObject *self)
00201 {
00202        Py_nsIID *s_iid = (Py_nsIID *)self;
00203        char buf[256];
00204        char *sziid = s_iid->m_iid.ToString();
00205        sprintf(buf, "_xpcom.IID('%s')", sziid);
00206        nsMemory::Free(sziid);
00207        return PyString_FromString(buf);
00208 }
00209 
00210 /* static */ PyObject *
00211 Py_nsIID::PyTypeMethod_str(PyObject *self)
00212 {
00213        Py_nsIID *s_iid = (Py_nsIID *)self;
00214        char *sziid = s_iid->m_iid.ToString();
00215        PyObject *ret = PyString_FromString(sziid);
00216        nsMemory::Free(sziid);
00217        return ret;
00218 }
00219 
00220 /* static */long
00221 Py_nsIID::PyTypeMethod_hash(PyObject *self)
00222 {
00223        const nsIID &iid = ((Py_nsIID *)self)->m_iid;
00224 
00225        long ret = iid.m0 + iid.m1 + iid.m2;
00226        for (int i=0;i<7;i++)
00227               ret += iid.m3[i];
00228        if ( ret == -1 )
00229               return -2;
00230        return ret;
00231 }
00232 
00233 /*static*/ void
00234 Py_nsIID::PyTypeMethod_dealloc(PyObject *ob)
00235 {
00236        delete (Py_nsIID *)ob;
00237 }