Back to index

lightning-sunbird  0.9+nobinonly
Classes | Defines | Functions
VariantUtils.cpp File Reference
#include "PyXPCOM_std.h"
#include <nsIInterfaceInfoManager.h>
#include <nsAString.h>
#include <nsString.h>
#include <nsReadableUtils.h>

Go to the source code of this file.

Classes

struct  BVFTResult
class  PythonTypeDescriptor

Defines

#define FILL_SIMPLE_POINTER(type, val)   *((type *)pthis) = (type)(val)
#define BREAK_FALSE   {rc=PR_FALSE;break;}
#define GET_FROM_V(Type, FuncGet, FuncConvert)
#define MAKE_VALUE_BUFFER(size)
#define DEREF_IN_OR_OUT(element, ret_type)   (ret_type)(is_out ? *((ret_type *)ns_v.val.p) : (ret_type)(element))
#define FILL_SIMPLE_POINTER(type, ob)   *((type *)ns_v.val.p) = (type)(ob)

Functions

PRBool IsNullDOMString (const nsAString &aString)
PRBool IsNullDOMString (const nsACString &aString)
static int PyUnicode_AsPRUnichar (PyObject *obj, PRUnichar **dest_out, PRUint32 *size_out)
PyObject * PyObject_FromNSString (const nsACString &s, PRBool bAssumeUTF8=PR_FALSE)
PyObject * PyObject_FromNSString (const nsAString &s)
static PRUint32 GetArrayElementSize (PRUint8 t)
void FreeSingleArray (void *array_ptr, PRUint32 sequence_size, PRUint8 array_type)
PRBool FillSingleArray (void *array_ptr, PyObject *sequence_ob, PRUint32 sequence_size, PRUint32 array_element_size, PRUint8 array_type)
PyObject * UnpackSingleArray (void *array_ptr, PRUint32 sequence_size, PRUint8 array_type, nsIID *iid)
static PRUint16 BestVariantTypeForPyObject (PyObject *ob, BVFTResult *pdata=NULL)
nsIVariantPyObject_AsVariant (PyObject *ob)
static PyObject * MyBool_FromBool (PRBool v)
static PyObject * MyObject_FromInterface (nsISupports *p)
PyObject * PyObject_FromVariantArray (nsIVariant *v)
PyObject * PyObject_FromVariant (nsIVariant *v)
static int ProcessPythonTypeDescriptors (PythonTypeDescriptor *pdescs, int num)

Define Documentation

Definition at line 247 of file VariantUtils.cpp.

#define DEREF_IN_OR_OUT (   element,
  ret_type 
)    (ret_type)(is_out ? *((ret_type *)ns_v.val.p) : (ret_type)(element))

Definition at line 1916 of file VariantUtils.cpp.

#define FILL_SIMPLE_POINTER (   type,
  val 
)    *((type *)pthis) = (type)(val)

Definition at line 2148 of file VariantUtils.cpp.

#define FILL_SIMPLE_POINTER (   type,
  ob 
)    *((type *)ns_v.val.p) = (type)(ob)

Definition at line 2148 of file VariantUtils.cpp.

#define GET_FROM_V (   Type,
  FuncGet,
  FuncConvert 
)
Value:
{ \
	Type t; \
       if (NS_FAILED(nr = FuncGet( &t ))) goto done;\
       ret = FuncConvert(t);\
       break; \
}

Definition at line 711 of file VariantUtils.cpp.

Value:
if ((this_buffer_pointer = (void *)nsMemory::Alloc((size))) == nsnull) { \
              PyErr_NoMemory(); \
              BREAK_FALSE; \
       }

Definition at line 1097 of file VariantUtils.cpp.


Function Documentation

static PRUint16 BestVariantTypeForPyObject ( PyObject *  ob,
BVFTResult pdata = NULL 
) [static]

Definition at line 547 of file VariantUtils.cpp.

{
       nsISupports *ps = NULL;
       nsIID iid;
       // start with some fast concrete checks.
       if (ob==Py_None)
              return nsIDataType::VTYPE_EMPTY;
       if (ob==Py_True || ob == Py_False)
              return nsIDataType::VTYPE_BOOL;
       if (PyInt_Check(ob))
              return nsIDataType::VTYPE_INT32;
       if (PyLong_Check(ob))
              return nsIDataType::VTYPE_INT64;
       if (PyFloat_Check(ob))
              return nsIDataType::VTYPE_DOUBLE;
       if (PyString_Check(ob))
              return nsIDataType::VTYPE_STRING_SIZE_IS;
       if (PyUnicode_Check(ob))
              return nsIDataType::VTYPE_WSTRING_SIZE_IS;
       if (PyTuple_Check(ob) || PyList_Check(ob)) {
              if (PySequence_Length(ob))
                     return nsIDataType::VTYPE_ARRAY;
              return nsIDataType::VTYPE_EMPTY_ARRAY;
       }
       // Now do expensive or abstract checks.
       if (Py_nsISupports::InterfaceFromPyObject(ob, NS_GET_IID(nsISupports), &ps, PR_TRUE)) {
              if (pdata) {
                     pdata->pis = ps;
                     pdata->iid = NS_GET_IID(nsISupports);
              } else
                     ps->Release();
              return nsIDataType::VTYPE_INTERFACE_IS;
       } else
              PyErr_Clear();
       if (Py_nsIID::IIDFromPyObject(ob, &iid)) {
              if (pdata)
                     pdata->iid = iid;
              return nsIDataType::VTYPE_ID;
       } else
              PyErr_Clear();
       if (PySequence_Check(ob)) {
              if (PySequence_Length(ob))
                     return nsIDataType::VTYPE_ARRAY;
              return nsIDataType::VTYPE_EMPTY_ARRAY;
       }
       return (PRUint16)-1;
}

Here is the caller graph for this function:

PRBool FillSingleArray ( void array_ptr,
PyObject *  sequence_ob,
PRUint32  sequence_size,
PRUint32  array_element_size,
PRUint8  array_type 
)

Definition at line 250 of file VariantUtils.cpp.

{
       PRUint8 *pthis = (PRUint8 *)array_ptr;
       NS_ABORT_IF_FALSE(pthis, "Don't have a valid array to fill!");
       PRBool rc = PR_TRUE;
       // We handle T_U8 specially as a string/Unicode.
       // If it is NOT a string, we just fall through and allow the standard
       // sequence unpack code process it (just slower!)
       if ( array_type == nsXPTType::T_U8 && 
              (PyString_Check(sequence_ob) || PyUnicode_Check(sequence_ob))) {

              PRBool release_seq;
              if (PyUnicode_Check(sequence_ob)) {
                     release_seq = PR_TRUE;
                     sequence_ob = PyObject_Str(sequence_ob);
              } else
                     release_seq = PR_FALSE;
              if (!sequence_ob) // presumably a memory error, or Unicode encoding error.
                     return PR_FALSE;
              memcpy(pthis, PyString_AS_STRING(sequence_ob), sequence_size);
              if (release_seq)
                     Py_DECREF(sequence_ob);
              return PR_TRUE;
       }

       for (PRUint32 i=0; rc && i<sequence_size; i++,pthis += array_element_size) {
              PyObject *val = PySequence_GetItem(sequence_ob, i);
              PyObject *val_use = NULL;
              if (val==NULL)
                     return PR_FALSE;
              switch(array_type) {
                       case nsXPTType::T_I8:
                            if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE;
                            FILL_SIMPLE_POINTER( PRInt8, PyInt_AsLong(val_use) );
                            break;
                       case nsXPTType::T_I16:
                            if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE;
                            FILL_SIMPLE_POINTER( PRInt16, PyInt_AsLong(val_use) );
                            break;
                       case nsXPTType::T_I32:
                            if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE;
                            FILL_SIMPLE_POINTER( PRInt32, PyInt_AsLong(val_use) );
                            break;
                       case nsXPTType::T_I64:
                            if ((val_use=PyNumber_Long(val))==NULL) BREAK_FALSE;
                            FILL_SIMPLE_POINTER( PRInt64, PyLong_AsLongLong(val_use) );
                            break;
                       case nsXPTType::T_U8:
                            if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE;
                            FILL_SIMPLE_POINTER( PRUint8, PyInt_AsLong(val_use) );
                            break;
                       case nsXPTType::T_U16:
                            if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE;
                            FILL_SIMPLE_POINTER( PRUint16, PyInt_AsLong(val_use) );
                            break;
                       case nsXPTType::T_U32:
                            if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE;
                            FILL_SIMPLE_POINTER( PRUint32, PyInt_AsLong(val_use) );
                            break;
                       case nsXPTType::T_U64:
                            if ((val_use=PyNumber_Long(val))==NULL) BREAK_FALSE;
                            FILL_SIMPLE_POINTER( PRUint64, PyLong_AsUnsignedLongLong(val_use) );
                            break;
                       case nsXPTType::T_FLOAT:
                            if ((val_use=PyNumber_Float(val))==NULL) BREAK_FALSE
                            FILL_SIMPLE_POINTER( float, PyFloat_AsDouble(val_use) );
                            break;
                       case nsXPTType::T_DOUBLE:
                            if ((val_use=PyNumber_Float(val))==NULL) BREAK_FALSE
                            FILL_SIMPLE_POINTER( double, PyFloat_AsDouble(val_use) );
                            break;
                       case nsXPTType::T_BOOL:
                            if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE
                            FILL_SIMPLE_POINTER( PRBool, PyInt_AsLong(val_use) );
                            break;
                       case nsXPTType::T_CHAR:
                            if (!PyString_Check(val) && !PyUnicode_Check(val)) {
                                   PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
                                   BREAK_FALSE;
                            }
                            if ((val_use = PyObject_Str(val))==NULL)
                                   BREAK_FALSE;
                            // Sanity check should PyObject_Str() ever loosen its semantics wrt Unicode!
                            NS_ABORT_IF_FALSE(PyString_Check(val_use), "PyObject_Str didnt return a string object!");
                            FILL_SIMPLE_POINTER( char, *PyString_AS_STRING(val_use) );
                            break;

                       case nsXPTType::T_WCHAR:
                            if (!PyString_Check(val) && !PyUnicode_Check(val)) {
                                   PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
                                   BREAK_FALSE;
                            }
                            if ((val_use = PyUnicode_FromObject(val)) == NULL)
                                   BREAK_FALSE;
                            NS_ABORT_IF_FALSE(PyUnicode_Check(val_use), "PyUnicode_FromObject didnt return a Unicode object!");
                            // Lossy!
                            FILL_SIMPLE_POINTER( PRUnichar, *PyUnicode_AS_UNICODE(val_use) );
                            break;

                       case nsXPTType::T_IID: {
                            nsIID iid;
                            if (!Py_nsIID::IIDFromPyObject(val, &iid))
                                   BREAK_FALSE;
                            nsIID **pp = (nsIID **)pthis;
                            // If there is an existing IID, free it.
                            if (*pp)
                                   nsMemory::Free(*pp);
                            *pp = (nsIID *)nsMemory::Alloc(sizeof(nsIID));
                            if (*pp==NULL) {
                                   PyErr_NoMemory();
                                   BREAK_FALSE;
                            }
                            memcpy(*pp, &iid, sizeof(iid));
                            break;
                            }

              //          case nsXPTType::T_BSTR:

                       case nsXPTType::T_CHAR_STR: {
                            // If it is an existing string, free it.
                            char **pp = (char **)pthis;
                            if (*pp)
                                   nsMemory::Free(*pp);
                            *pp = nsnull;

                            if (val == Py_None)
                                   break; // Remains NULL.
                            if (!PyString_Check(val) && !PyUnicode_Check(val)) {
                                   PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
                                   BREAK_FALSE;
                            }
                            if ((val_use = PyObject_Str(val))==NULL)
                                   BREAK_FALSE;
                            // Sanity check should PyObject_Str() ever loosen its semantics wrt Unicode!
                            NS_ABORT_IF_FALSE(PyString_Check(val_use), "PyObject_Str didnt return a string object!");

                            const char *sz = PyString_AS_STRING(val_use);
                            int nch = PyString_GET_SIZE(val_use);

                            *pp = (char *)nsMemory::Alloc(nch+1);
                            if (*pp==NULL) {
                                   PyErr_NoMemory();
                                   BREAK_FALSE;
                            }
                            strncpy(*pp, sz, nch+1);
                            break;
                            }
                       case nsXPTType::T_WCHAR_STR: {
                            // If it is an existing string, free it.
                            PRUnichar **pp = (PRUnichar **)pthis;
                            if (*pp)
                                   nsMemory::Free(*pp);
                            *pp = nsnull;
                            if (val == Py_None)
                                   break; // Remains NULL.
                            if (!PyString_Check(val) && !PyUnicode_Check(val)) {
                                   PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
                                   BREAK_FALSE;
                            }
                            if ((val_use = PyUnicode_FromObject(val))==NULL)
                                   BREAK_FALSE;
                            NS_ABORT_IF_FALSE(PyUnicode_Check(val_use), "PyUnicode_FromObject didnt return a Unicode object!");
                            if (PyUnicode_AsPRUnichar(val_use, pp, NULL) < 0)
                                   BREAK_FALSE;
                            break;
                            }
                       case nsXPTType::T_INTERFACE_IS: // hmm - ignoring the IID can't be good :(
                       case nsXPTType::T_INTERFACE:  {
                            // We do allow NULL here, even tho doing so will no-doubt crash some objects.
                            // (but there will certainly be objects out there that will allow NULL :-(
                            nsISupports *pnew;
                            if (!Py_nsISupports::InterfaceFromPyObject(val, NS_GET_IID(nsISupports), &pnew, PR_TRUE))
                                   BREAK_FALSE;
                            nsISupports **pp = (nsISupports **)pthis;
                            if (*pp) {
                                   Py_BEGIN_ALLOW_THREADS; // MUST release thread-lock, incase a Python COM object that re-acquires.
                                   (*pp)->Release();
                                   Py_END_ALLOW_THREADS;
                            }
                            *pp = pnew; // ref-count added by InterfaceFromPyObject
                            break;
                            }
                     default:
                            // try and limp along in this case.
                            // leave rc TRUE
                            PyXPCOM_LogWarning("Converting Python object for an array element - The object type (0x%x) is unknown - leaving param alone!\n", array_type);
                            break;
              }
              Py_XDECREF(val_use);
              Py_DECREF(val);
       }
       return rc;    
}

Here is the call graph for this function:

Here is the caller graph for this function:

void FreeSingleArray ( void array_ptr,
PRUint32  sequence_size,
PRUint8  array_type 
)

Definition at line 200 of file VariantUtils.cpp.

{
       // Free each array element - NOT the array itself
       // Thus, we only need to free arrays or pointers.
       void **p = (void **)array_ptr;
       PRUint32 i;
       switch(array_type & XPT_TDP_TAGMASK) {
              case nsXPTType::T_IID:
              case nsXPTType::T_CHAR_STR:
              case nsXPTType::T_WCHAR_STR:
                     for (i=0; i<sequence_size; i++)
                            if (p[i]) nsMemory::Free(p[i]);
                     break;
              case nsXPTType::T_INTERFACE:
              case nsXPTType::T_INTERFACE_IS:
                     for (i=0; i<sequence_size; i++)
                            if (p[i]) {
                                   Py_BEGIN_ALLOW_THREADS; // MUST release thread-lock, incase a Python COM object that re-acquires.
                                   ((nsISupports *)p[i])->Release();
                                   Py_END_ALLOW_THREADS;
                            }
                     break;

              // Ones we know need no deallocation
              case nsXPTType::T_U8:
              case nsXPTType::T_I8:
              case nsXPTType::T_I16:
              case nsXPTType::T_U16:
              case nsXPTType::T_I32:
              case nsXPTType::T_U32:
              case nsXPTType::T_I64:
              case nsXPTType::T_U64:
              case nsXPTType::T_FLOAT:
              case nsXPTType::T_DOUBLE:
              case nsXPTType::T_BOOL:
              case nsXPTType::T_CHAR:
              case nsXPTType::T_WCHAR:
                     break;

              // And a warning should new type codes appear, as they may need deallocation.
              default:
                     PyXPCOM_LogWarning("Deallocating unknown type %d (0x%x) - possible memory leak\n");
                     break;
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PRUint32 GetArrayElementSize ( PRUint8  t) [static]

Definition at line 144 of file VariantUtils.cpp.

{
       PRUint32 ret;
       switch (t & XPT_TDP_TAGMASK) {
              case nsXPTType::T_U8:
              case nsXPTType::T_I8:
                     ret = sizeof(PRInt8); 
                     break;
              case nsXPTType::T_I16:
              case nsXPTType::T_U16:
                     ret = sizeof(PRInt16); 
                     break;
              case nsXPTType::T_I32:
              case nsXPTType::T_U32:
                     ret = sizeof(PRInt32); 
                     break;
              case nsXPTType::T_I64:
              case nsXPTType::T_U64:
                     ret = sizeof(PRInt64); 
                     break;
              case nsXPTType::T_FLOAT:
                     ret = sizeof(float); 
                     break;
              case nsXPTType::T_DOUBLE:
                     ret = sizeof(double); 
                     break;
              case nsXPTType::T_BOOL:
                     ret = sizeof(PRBool); 
                     break;
              case nsXPTType::T_CHAR:
                     ret = sizeof(char); 
                     break;
              case nsXPTType::T_WCHAR:
                     ret = sizeof(PRUnichar); 
                     break;
              case nsXPTType::T_IID:
              case nsXPTType::T_CHAR_STR:
              case nsXPTType::T_WCHAR_STR:
              case nsXPTType::T_INTERFACE:
              case nsXPTType::T_DOMSTRING:
              case nsXPTType::T_INTERFACE_IS:
              case nsXPTType::T_PSTRING_SIZE_IS:
              case nsXPTType::T_CSTRING:
              case nsXPTType::T_ASTRING:
              case nsXPTType::T_UTF8STRING:

                     ret = sizeof( void * );
                     break;
       default:
              NS_ABORT_IF_FALSE(0, "Unknown array type code!");
              ret = 0;
              break;
       }
       return ret;
}

Here is the caller graph for this function:

PRBool IsNullDOMString ( const nsAString &  aString) [inline]

Definition at line 63 of file VariantUtils.cpp.

{
       return PR_FALSE;
}

Here is the caller graph for this function:

PRBool IsNullDOMString ( const nsACString &  aString) [inline]

Definition at line 70 of file VariantUtils.cpp.

{
       return PR_FALSE;
}
static PyObject* MyBool_FromBool ( PRBool  v) [static]

Definition at line 700 of file VariantUtils.cpp.

{
       PyObject *ret = v ? Py_True : Py_False;
       Py_INCREF(ret);
       return ret;
}

Here is the caller graph for this function:

static PyObject* MyObject_FromInterface ( nsISupports *  p) [static]

Definition at line 706 of file VariantUtils.cpp.

{
       return Py_nsISupports::PyObjectFromInterface(p, NS_GET_IID(nsISupports), PR_FALSE);
}

Here is the caller graph for this function:

static int ProcessPythonTypeDescriptors ( PythonTypeDescriptor pdescs,
int  num 
) [static]

Definition at line 853 of file VariantUtils.cpp.

{
       // Loop over the array, checking all the params marked as having an arg.
       // If these args nominate another arg as the size_is param, then
       // we reset the size_is param to _not_ requiring an arg.
       int i;
       for (i=0;i<num;i++) {
              PythonTypeDescriptor &ptd = pdescs[i];
              // Can't use XPT_TDP_TAG() - it uses a ".flags" reference in the macro.
              switch (ptd.type_flags & XPT_TDP_TAGMASK) {
                     case nsXPTType::T_ARRAY:
                            NS_ABORT_IF_FALSE(ptd.argnum < num, "Bad dependent index");
                            if (ptd.argnum2 < num) {
                                   if (XPT_PD_IS_IN(ptd.param_flags))
                                          pdescs[ptd.argnum2].is_auto_in = PR_TRUE;
                                   if (XPT_PD_IS_OUT(ptd.param_flags))
                                          pdescs[ptd.argnum2].is_auto_out = PR_TRUE;
                            }
                            break;
                     case nsXPTType::T_PSTRING_SIZE_IS:
                     case nsXPTType::T_PWSTRING_SIZE_IS:
                            NS_ABORT_IF_FALSE(ptd.argnum < num, "Bad dependent index");
                            if (ptd.argnum < num) {
                                   if (XPT_PD_IS_IN(ptd.param_flags))
                                          pdescs[ptd.argnum].is_auto_in = PR_TRUE;
                                   if (XPT_PD_IS_OUT(ptd.param_flags))
                                          pdescs[ptd.argnum].is_auto_out = PR_TRUE;
                            }
                            break;
                     default:
                            break;
              }
       }
       int total_params_needed = 0;
       for (i=0;i<num;i++)
              if (XPT_PD_IS_IN(pdescs[i].param_flags) && !pdescs[i].is_auto_in && !XPT_PD_IS_DIPPER(pdescs[i].param_flags))
                     total_params_needed++;

       return total_params_needed;
}
nsIVariant* PyObject_AsVariant ( PyObject *  ob)

Definition at line 595 of file VariantUtils.cpp.

{
       nsresult nr = NS_ERROR_UNEXPECTED;
       nsCOMPtr<nsIWritableVariant> v = do_CreateInstance("@mozilla.org/variant;1", &nr); 
       if (NS_FAILED(nr)) {
              PyXPCOM_BuildPyException(nr);
              return NULL;
       }
       // *sigh* - I tried the abstract API (PyNumber_Check, etc)
       // but our COM instances too often qualify.
       BVFTResult cvt_result;
       PRUint16 dt = BestVariantTypeForPyObject(ob, &cvt_result);
       switch (dt) {
              case nsIDataType::VTYPE_BOOL:
                     nr = v->SetAsBool(ob==Py_True);
                     break;
              case nsIDataType::VTYPE_INT32:
                     nr = v->SetAsInt32(PyInt_AsLong(ob));
                     break;
              case nsIDataType::VTYPE_INT64:
                     nr = v->SetAsInt64(PyLong_AsLongLong(ob));
                     break;
              case nsIDataType::VTYPE_DOUBLE:
                     nr = v->SetAsDouble(PyFloat_AsDouble(ob));
                     break;
              case nsIDataType::VTYPE_STRING_SIZE_IS:
                     nr = v->SetAsStringWithSize(PyString_Size(ob), PyString_AsString(ob));
                     break;
              case nsIDataType::VTYPE_WSTRING_SIZE_IS:
                     if (PyUnicode_GetSize(ob) == 0) {
                            nr = v->SetAsWStringWithSize(0, (PRUnichar*)NULL);
                     }
                     else {
                            PRUint32 nch;
                            PRUnichar *p;
                            if (PyUnicode_AsPRUnichar(ob, &p, &nch) < 0) {
                                   nr = NS_ERROR_UNEXPECTED;
                                   break;
                            }
                            nr = v->SetAsWStringWithSize(nch, p);
                            nsMemory::Free(p);
                     }
                     break;
              case nsIDataType::VTYPE_INTERFACE_IS:
              {
                     nsISupports *ps = cvt_result.pis;
                     nr = v->SetAsInterface(cvt_result.iid, ps);
                     if (ps) {
                            Py_BEGIN_ALLOW_THREADS; // MUST release thread-lock, incase a Python COM object that re-acquires.
                            ps->Release();
                            Py_END_ALLOW_THREADS;
                     }
                     break;
              }
              case nsIDataType::VTYPE_ID:
                     nr = v->SetAsID(cvt_result.iid);
                     break;
              case nsIDataType::VTYPE_ARRAY:
              {
                     int seq_length = PySequence_Length(ob);
                     NS_ABORT_IF_FALSE(seq_length!=0, "VTYPE_ARRAY assumes at least one element!");
                     PyObject *first = PySequence_GetItem(ob, 0);
                     if (!first) break;
                     int array_type = BestVariantTypeForPyObject(first);
                     Py_DECREF(first);
                     // Arrays can't handle all types.  This means we lost embedded NULLs.
                     // This should really be fixed in XPCOM.
                     if (array_type == nsIDataType::VTYPE_STRING_SIZE_IS) array_type = nsIDataType::VTYPE_CHAR_STR;
                     if (array_type == nsIDataType::VTYPE_WSTRING_SIZE_IS) array_type = nsIDataType::VTYPE_WCHAR_STR;
                     PRUint32 element_size = GetArrayElementSize(array_type);
                     int cb_buffer_pointer = seq_length * element_size;
                     void *buffer_pointer;
                     if ((buffer_pointer = (void *)nsMemory::Alloc(cb_buffer_pointer)) == nsnull) {
                            PyErr_NoMemory();
                            nr = NS_ERROR_UNEXPECTED;
                            break;
                     }
                     memset(buffer_pointer, 0, cb_buffer_pointer);
                     if (FillSingleArray(buffer_pointer, ob, seq_length, element_size, array_type)) {
                            nr = v->SetAsArray(array_type, &NS_GET_IID(nsISupports), seq_length, buffer_pointer);
                            FreeSingleArray(buffer_pointer, seq_length, array_type);
                     } else
                            nr = NS_ERROR_UNEXPECTED;
                     nsMemory::Free(buffer_pointer);
                     break;
              }
              case nsIDataType::VTYPE_EMPTY:
                     v->SetAsEmpty();
                     break;
              case nsIDataType::VTYPE_EMPTY_ARRAY:
                     v->SetAsEmptyArray();
                     break;
              case (PRUint16)-1:
                     PyErr_Format(PyExc_TypeError, "Objects of type '%s' can not be converted to an nsIVariant", ob->ob_type->tp_name);
                     return NULL;
              default:
                     NS_ABORT_IF_FALSE(0, "BestVariantTypeForPyObject() returned a variant type not handled here!");
                     PyErr_Format(PyExc_TypeError, "Objects of type '%s' can not be converted to an nsIVariant", ob->ob_type->tp_name);
                     return NULL;
       }
       nsIVariant *ret;
       v->QueryInterface(NS_GET_IID(nsIVariant), (void **)&ret);
       return ret;
}

Here is the call graph for this function:

PyObject* PyObject_FromNSString ( const nsACString &  s,
PRBool  bAssumeUTF8 = PR_FALSE 
)

Definition at line 107 of file VariantUtils.cpp.

{
       PyObject *ret;
       if (IsNullDOMString(s)) {
              ret = Py_None;
              Py_INCREF(Py_None);
       } else {
              if (bAssumeUTF8) {
                        const nsPromiseFlatCString& temp = PromiseFlatCString(s);
                        ret = PyUnicode_DecodeUTF8(temp.get(), temp.Length(), NULL);
              } else {
                     ret = PyString_FromStringAndSize(NULL, s.Length());
                     if (!ret)
                            return NULL;
                     // Need "CopyAsciiTo"!?
                     nsACString::const_iterator fromBegin, fromEnd;
                     char* dest = PyString_AS_STRING(ret);
                     copy_string(s.BeginReading(fromBegin), s.EndReading(fromEnd), dest);
              }
       }
       return ret;
}

Here is the call graph for this function:

Here is the caller graph for this function:

PyObject* PyObject_FromNSString ( const nsAString &  s)

Definition at line 130 of file VariantUtils.cpp.

{
       PyObject *ret;
       if (IsNullDOMString(s)) {
              ret = Py_None;
              Py_INCREF(Py_None);
       } else {
                const nsPromiseFlatString& temp = PromiseFlatString(s);
                ret = PyUnicode_FromPRUnichar(temp.get(), temp.Length());
       }
       return ret;
}

Here is the call graph for this function:

PyObject* PyObject_FromVariant ( nsIVariant v)

Definition at line 741 of file VariantUtils.cpp.

{
       if (!v) {
              Py_INCREF(Py_None);
              return Py_None;
       }
       PRUint16 dt;
       nsresult nr;
       PyObject *ret = NULL;
       nr = v->GetDataType(&dt);
       if (NS_FAILED(nr)) goto done;
       switch (dt) {
              case nsIDataType::VTYPE_VOID:
              case nsIDataType::VTYPE_EMPTY:
              case nsIDataType::VTYPE_EMPTY_ARRAY:
                     ret = Py_None;
                     Py_INCREF(Py_None);
                     break;
              case nsIDataType::VTYPE_ARRAY:
                     ret = PyObject_FromVariantArray(v);
                     break;
              case nsIDataType::VTYPE_INT8:
              case nsIDataType::VTYPE_INT16:
              case nsIDataType::VTYPE_INT32:
                     GET_FROM_V(PRInt32, v->GetAsInt32, PyInt_FromLong);
              case nsIDataType::VTYPE_UINT8:
              case nsIDataType::VTYPE_UINT16:
              case nsIDataType::VTYPE_UINT32:
                     GET_FROM_V(PRUint32, v->GetAsUint32, PyLong_FromUnsignedLong);
              case nsIDataType::VTYPE_INT64:
                     GET_FROM_V(PRInt64, v->GetAsInt64, PyLong_FromLongLong);
              case nsIDataType::VTYPE_UINT64:
                     GET_FROM_V(PRUint64, v->GetAsUint64, PyLong_FromUnsignedLongLong);
              case nsIDataType::VTYPE_FLOAT:
              case nsIDataType::VTYPE_DOUBLE:
                     GET_FROM_V(double, v->GetAsDouble, PyFloat_FromDouble);
              case nsIDataType::VTYPE_BOOL:
                     GET_FROM_V(PRBool, v->GetAsBool, MyBool_FromBool);
              default:
                     PyXPCOM_LogWarning("Converting variant to Python object - variant type '%d' unknown - using string.\n", dt);
              // Fall through to the string case
              case nsIDataType::VTYPE_CHAR:
              case nsIDataType::VTYPE_CHAR_STR:
              case nsIDataType::VTYPE_STRING_SIZE_IS:
              case nsIDataType::VTYPE_CSTRING: {
                     nsCAutoString s;
                     if (NS_FAILED(nr=v->GetAsACString(s))) goto done;
                     ret = PyObject_FromNSString(s);
                     break;
              }
              case nsIDataType::VTYPE_WCHAR:
              case nsIDataType::VTYPE_DOMSTRING:
              case nsIDataType::VTYPE_WSTRING_SIZE_IS:
              case nsIDataType::VTYPE_ASTRING: {
                     nsAutoString s;
                     if (NS_FAILED(nr=v->GetAsAString(s))) goto done;
                     ret = PyObject_FromNSString(s);
                     break;
              }
              case nsIDataType::VTYPE_ID:
                     GET_FROM_V(nsIID, v->GetAsID, Py_nsIID::PyObjectFromIID);
              case nsIDataType::VTYPE_INTERFACE:
                     GET_FROM_V(nsISupports *, v->GetAsISupports, MyObject_FromInterface);
              case nsIDataType::VTYPE_INTERFACE_IS: {
                     nsISupports *p;
                     nsIID *iid;
                     if (NS_FAILED(nr=v->GetAsInterface(&iid, (void **)&p))) goto done;
                     ret = Py_nsISupports::PyObjectFromInterface(p, *iid, PR_FALSE);
                     break;
              // case nsIDataType::VTYPE_WCHAR_STR
              // case nsIDataType::VTYPE_UTF8STRING
              }
       }
done:
       if (NS_FAILED(nr)) {
              NS_ABORT_IF_FALSE(ret==NULL, "Have an error, but also a return val!");
              PyXPCOM_BuildPyException(nr);
       }
       return ret;
}

Here is the call graph for this function:

Definition at line 718 of file VariantUtils.cpp.

{
       nsresult nr;
       NS_PRECONDITION(v, "NULL variant!");
       if (!v)
              return PyXPCOM_BuildPyException(NS_ERROR_INVALID_POINTER);
#ifdef NS_DEBUG
       PRUint16 dt;
       nr = v->GetDataType(&dt);
       NS_ABORT_IF_FALSE(dt == nsIDataType::VTYPE_ARRAY, "expected an array variant");
#endif
       nsIID iid;
       void *p;
       PRUint16 type;
       PRUint32 count;
       nr = v->GetAsArray(&type, &iid, &count, &p);
       if (NS_FAILED(nr)) return PyXPCOM_BuildPyException(nr);
       PyObject *ret = UnpackSingleArray(p, count, (PRUint8)type, &iid);
       FreeSingleArray(p, count, (PRUint8)type);
       nsMemory::Free(p);
       return ret;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int PyUnicode_AsPRUnichar ( PyObject *  obj,
PRUnichar **  dest_out,
PRUint32 size_out 
) [static]

Definition at line 79 of file VariantUtils.cpp.

{
       PRUint32 size;
       PyObject *s;
       PRUnichar *dest;

       s = PyUnicode_AsUTF16String(obj);
       if (!s)
              return -1;
       size = (PyString_GET_SIZE(s) - 2) / sizeof(PRUnichar);
       dest = (PRUnichar *)nsMemory::Alloc(sizeof(PRUnichar) * (size + 1));
       if (!dest) {
              PyErr_NoMemory();
              Py_DECREF(s);
              return -1;
       }
       // Drop the UTF-16 byte order mark at the beginning of
       // the string.  (See the docs on PyUnicode_AsUTF16String.)
       // Some Mozilla libraries don't like the mark.
       memcpy(dest, PyString_AS_STRING(s) + 2, sizeof(PRUnichar) * size);
       Py_DECREF(s);
       dest[size] = 0;
       *dest_out = dest;
       if (size_out)
              *size_out = size;
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

PyObject* UnpackSingleArray ( void array_ptr,
PRUint32  sequence_size,
PRUint8  array_type,
nsIID iid 
)

Definition at line 444 of file VariantUtils.cpp.

{
       if (array_ptr==NULL) {
              Py_INCREF(Py_None);
              return Py_None;
       }
       if (array_type == nsXPTType::T_U8)
              return PyString_FromStringAndSize( (char *)array_ptr, sequence_size );

       PRUint32 array_element_size = GetArrayElementSize(array_type);
       PyObject *list_ret = PyList_New(sequence_size);
       PRUint8 *pthis = (PRUint8 *)array_ptr;
       for (PRUint32 i=0; i<sequence_size; i++,pthis += array_element_size) {
              PyObject *val = NULL;
              switch(array_type) {
                       case nsXPTType::T_I8:
                            val = PyInt_FromLong( *((PRInt8 *)pthis) );
                            break;
                       case nsXPTType::T_I16:
                            val = PyInt_FromLong( *((PRInt16 *)pthis) );
                            break;
                       case nsXPTType::T_I32:
                            val = PyInt_FromLong( *((PRInt32 *)pthis) );
                            break;
                       case nsXPTType::T_I64:
                            val = PyLong_FromLongLong( *((PRInt64 *)pthis) );
                            break;
                       // case nsXPTType::T_U8 - handled above!
                       case nsXPTType::T_U16:
                            val = PyInt_FromLong( *((PRUint16 *)pthis) );
                            break;
                       case nsXPTType::T_U32:
                            val = PyInt_FromLong( *((PRUint32 *)pthis) );
                            break;
                       case nsXPTType::T_U64:
                            val = PyLong_FromUnsignedLongLong( *((PRUint64 *)pthis) );
                            break;
                       case nsXPTType::T_FLOAT:
                            val = PyFloat_FromDouble( *((float*)pthis) );
                            break;
                       case nsXPTType::T_DOUBLE:
                            val = PyFloat_FromDouble( *((double*)pthis) );
                            break;
                       case nsXPTType::T_BOOL:
                            val = (*((PRBool *)pthis)) ? Py_True : Py_False;
                            Py_INCREF(val);
                            break;
                       case nsXPTType::T_IID:
                            val = Py_nsIID::PyObjectFromIID( **((nsIID **)pthis) );
                            break;

                       case nsXPTType::T_CHAR_STR: {
                            char **pp = (char **)pthis;
                            if (*pp==NULL) {
                                   Py_INCREF(Py_None);
                                   val = Py_None;
                            } else
                                   val = PyString_FromString(*pp);
                            break;
                            }
                       case nsXPTType::T_WCHAR_STR: {
                            PRUnichar **pp = (PRUnichar **)pthis;
                            if (*pp==NULL) {
                                   Py_INCREF(Py_None);
                                   val = Py_None;
                            } else {
                                   val = PyUnicode_FromPRUnichar( *pp, nsCRT::strlen(*pp) );
                            }
                            break;
                            }
                       case nsXPTType::T_INTERFACE_IS:
                       case nsXPTType::T_INTERFACE: {
                            nsISupports **pp = (nsISupports **)pthis;
                            val = Py_nsISupports::PyObjectFromInterface(*pp, iid ? *iid : NS_GET_IID(nsISupports), PR_TRUE);
                            break;
                            }
                       default: {
                            char buf[128];
                            sprintf(buf, "Unknown XPCOM array type flags (0x%x)", array_type);
                            PyXPCOM_LogWarning("%s - returning a string object with this message!\n", buf);
                            val = PyString_FromString(buf);
                            break;
                            }
              }
              if (val==NULL) {
                     NS_ABORT_IF_FALSE(PyErr_Occurred(), "NULL result in array conversion, but no error set!");
                     return NULL;
              }
              PyList_SET_ITEM(list_ret, i, val); // ref-count consumed.
       }
       return list_ret;
}

Here is the call graph for this function:

Here is the caller graph for this function: