* Allow arrays in Variants to hold elements of any type, by using

nsIVariant for each element.
* Return empty arrays as an empty list instead of None.
Not part of the default build.
This commit is contained in:
mhammond%skippinet.com.au 2006-10-16 09:30:04 +00:00
Родитель 1b27e37c4e
Коммит bcdf944293
3 изменённых файлов: 62 добавлений и 27 удалений

Просмотреть файл

@ -294,7 +294,7 @@ 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, nsIID *pIID)
PRUint32 array_element_size, PRUint8 array_type)
{
PRUint8 *pthis = (PRUint8 *)array_ptr;
NS_ABORT_IF_FALSE(pthis, "Don't have a valid array to fill!");
@ -708,30 +708,36 @@ PyObject_AsVariant( PyObject *ob, nsIVariant **aRet)
break;
case nsIDataType::VTYPE_ARRAY:
{
// To support arrays holding different data types,
// each element itself is a variant.
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) {
int i;
nsIVariant** buf = new nsIVariant*[seq_length]; // Create variant array.
if (!buf) {
nr = NS_ERROR_OUT_OF_MEMORY;
break;
}
memset(buffer_pointer, 0, cb_buffer_pointer);
if (FillSingleArray(buffer_pointer, ob, seq_length, element_size, array_type, nsnull)) {
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);
memset(buf, 0, sizeof(nsIVariant *) * seq_length);
for (i=0;NS_SUCCEEDED(nr) && i<seq_length;i++) {
PyObject *sub = PySequence_GetItem(ob, i);
if (!sub) {
nr = PyXPCOM_SetCOMErrorFromPyException();
break;
}
nr = PyObject_AsVariant(sub, buf+i);
Py_DECREF(sub);
}
if (NS_SUCCEEDED(nr)) {
nr = v->SetAsArray(nsXPTType::T_INTERFACE_IS,
&NS_GET_IID(nsIVariant),
seq_length, buf);
}
// Clean things up.
for (i=0;i<seq_length;i++) {
NS_IF_RELEASE(buf[i]);
}
delete [] buf;
break;
}
case nsIDataType::VTYPE_EMPTY:
@ -805,10 +811,12 @@ PyObject_FromVariant( Py_nsISupports *parent, nsIVariant *v)
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_EMPTY_ARRAY:
ret = PyList_New(0);
break;
case nsIDataType::VTYPE_ARRAY:
ret = PyObject_FromVariantArray(parent, v);
break;
@ -1489,7 +1497,7 @@ PRBool PyXPCOM_InterfaceVariantHelper::FillInVariant(const PythonTypeDescriptor
cb_this_buffer_pointer = 1;
MAKE_VALUE_BUFFER(cb_this_buffer_pointer);
memset(this_buffer_pointer, 0, cb_this_buffer_pointer);
rc = FillSingleArray(this_buffer_pointer, val, seq_length, element_size, array_type&XPT_TDP_TAGMASK, nsnull);
rc = FillSingleArray(this_buffer_pointer, val, seq_length, element_size, array_type&XPT_TDP_TAGMASK);
if (!rc) break;
rc = SetSizeIs(value_index, PR_FALSE, seq_length);
if (!rc) break;
@ -2591,7 +2599,7 @@ nsresult PyXPCOM_GatewayVariantHelper::BackFillVariant( PyObject *val, int index
bBackFill = pi->IsIn();
}
if (bBackFill)
rc = FillSingleArray(*(void **)ns_v.val.p, val, sequence_size, element_size, array_type&XPT_TDP_TAGMASK, piid);
rc = FillSingleArray(*(void **)ns_v.val.p, val, sequence_size, element_size, array_type&XPT_TDP_TAGMASK);
else {
// If it is an existing array, free it.
void **pp = (void **)ns_v.val.p;
@ -2606,7 +2614,7 @@ nsresult PyXPCOM_GatewayVariantHelper::BackFillVariant( PyObject *val, int index
if (nbytes==0) nbytes = 1; // avoid assertion about 0 bytes
*pp = (void *)nsMemory::Alloc(nbytes);
memset(*pp, 0, nbytes);
rc = FillSingleArray(*pp, val, sequence_size, element_size, array_type&XPT_TDP_TAGMASK, piid);
rc = FillSingleArray(*pp, val, sequence_size, element_size, array_type&XPT_TDP_TAGMASK);
if (!rc) break;
if (bCanSetSizeIs)
rc = SetSizeIs(index, PR_FALSE, sequence_size);

Просмотреть файл

@ -46,6 +46,19 @@ function MakeTestInterface()
return new clazz(iface);
}
// Taken from http://www.svendtofte.com/code/usefull_prototypes/prototypes.js
Array.prototype.compareArrays = function(arr) {
if (this.length != arr.length) return false;
for (var i = 0; i < arr.length; i++) {
if (this[i].compareArrays) { //likely nested array
if (!this[i].compareArrays(arr[i])) return false;
else continue;
}
if (this[i] != arr[i]) return false;
}
return true;
}
var c = new MakeTestInterface();
if (c.boolean_value != 1)
@ -135,4 +148,16 @@ count.value = 0;
var out = [];
c.DoubleStringArray(count, out);
print("javascript successfully tested the Python test component.");
v = new Array();
var v2 = c.CopyVariant(v);
if (!v.compareArrays(v2))
throw("Could not copy an empty array of nsIVariant");
v = new Array();
v[0] = 1;
v[1] = "test";
var v2 = c.CopyVariant(v);
if (!v.compareArrays(v2))
throw("Could not copy an empty array of nsIVariant");
print("OK: javascript successfully tested the Python test component.");

Просмотреть файл

@ -394,6 +394,7 @@ def test_derived_interface(c, test_flat = 0):
test_method(c.AppendArray, ([1,2,3],), [1,2,3])
test_method(c.AppendArray, ([1,2,3],[4,5,6]), [1,2,3,4,5,6])
test_method(c.CopyVariant, ([],), [])
test_method(c.CopyVariant, (None,), None)
test_method(c.CopyVariant, (1,), 1)
test_method(c.CopyVariant, (1.0,), 1.0)
@ -410,6 +411,7 @@ def test_derived_interface(c, test_flat = 0):
test_method(c.CopyVariant, ((c,c),), [c,c])
sup = c.queryInterface(xpcom.components.interfaces.nsISupports)._comobj_
test_method(c.CopyVariant, ((sup, sup),), [sup,sup])
test_method(c.CopyVariant, ([1,"test"],), [1,"test"])
test_method(c.AppendVariant, (1,2), 3)
test_method(c.AppendVariant, ((1,2),(3,4)), 10)
test_method(c.AppendVariant, ("bar", "foo"), "foobar")
@ -504,7 +506,7 @@ def test_from_js():
data = os.popen('xpcshell "' + fname + '"').readlines()
good = 0
for line in data:
if line.strip() == "javascript successfully tested the Python test component.":
if line.strip() == "OK: javascript successfully tested the Python test component.":
good = 1
if not good:
print "** The javascript test appeared to fail! Test output follows **"