#include "nsComponentManagerUtils.h"
#include "nsServiceManagerUtils.h"
#include "nsArrayUtils.h"
+#include "nsTArray.h"
#include "nsMemory.h"
#include "nsISupportsPrimitives.h"
#include "nsIProperties.h"
#include "bdb-debug.h"
-void addArrayDataToIter(void *data_ptr, PRUint32 count, PRUint16 type, DBusMessageIter *aIter, DBusSignatureIter *aSigIter);
+void addArrayDataToIter(void *data_ptr, PRUint32 start, PRUint32 count, PRUint16 type, DBusMessageIter *aIter, DBusSignatureIter *aSigIter);
void addJSValueToIter(JSContext *cx, jsval *aValue, DBusMessageIter *aIter, DBusSignatureIter *aSigIter);
static void
}
}
+PRUint16 getVType(int dType)
+{
+ switch (dType)
+ {
+ case DBUS_TYPE_BOOLEAN:
+ return nsIDataType::VTYPE_BOOL;
+ case DBUS_TYPE_BYTE:
+ return nsIDataType::VTYPE_INT8;
+ case DBUS_TYPE_INT16:
+ return nsIDataType::VTYPE_INT16;
+ case DBUS_TYPE_UINT16:
+ return nsIDataType::VTYPE_UINT16;
+ case DBUS_TYPE_INT32:
+ return nsIDataType::VTYPE_INT32;
+ case DBUS_TYPE_UINT32:
+ return nsIDataType::VTYPE_UINT32;
+ case DBUS_TYPE_DOUBLE:
+ return nsIDataType::VTYPE_DOUBLE;
+ case DBUS_TYPE_STRING:
+ case DBUS_TYPE_OBJECT_PATH:
+ case DBUS_TYPE_SIGNATURE:
+ return nsIDataType::VTYPE_WCHAR_STR;
+ default:
+ break;
+ }
+
+ return -1;
+}
+
+PRBool typesMatch(PRUint16 vType, int dType)
+{
+ return (vType == getVType(dType));
+}
+
void
addVariantToIter(nsIVariant *aVariant, DBusMessageIter *aIter, DBusSignatureIter *aSigIter)
{
PRUint16 variant_type;
aVariant->GetDataType(&variant_type);
- printf("addVariantToIter: signature \"%s\", type %c, variant type: %i\n",
+ BDBLOG(("addVariantToIter: signature \"%s\", type %c, variant type: %i\n",
element_signature,
element_type,
- variant_type);
+ variant_type));
if (dbus_type_is_basic(element_type))
{
{
/* TODO: Support for non-JS Dicts */
- BDBLOG((" add dict from variant\n"));
+ BDBLOG((" add dict from variant\n"));
nsCOMPtr<nsISupports> is;
nsIID *iid;
// Reported by a leak, dunno why?
+ // It's a comptr so it should go away with the end of context afaik
aVariant->GetAsInterface(&iid, getter_AddRefs(is));
// test argument for nsIXPConnectWrappedJS
for (int p = 0; p < props->length; p++)
{
- // get key signature from first property name
jsval propname;
nsCAutoString tmpsig;
JS_IdToValue(cx, props->vector[p], &propname);
JS_GetStringLength(prop_string),
&propvalue) == JS_TRUE)
{
- addJSValueToIter(cx, &propvalue, &dictIter, &dictSigIter);
+ nsIVariant *var = nsnull;
+ nsresult rs = xpc->JSToVariant(cx, propvalue, &var);
+ NS_ENSURE_SUCCESS(rs, );
+
+ addVariantToIter(var, &dictIter, &dictSigIter);
}
// Close the dict entry container
&count,
&data_ptr);
- BDBLOG((" getSignatureFromVariant: got %d elements of type %d\n", count, type));
- BDBLOG((" getSignatureFromVariant: got array signature %s\n", array_signature));
+ BDBLOG((" %s: got %d elements of type %d\n", __FUNCTION__, count, type));
+ BDBLOG((" %s: got array signature %s\n", __FUNCTION__, array_signature));
- DBusMessageIter arrayIter;
- if (dbus_message_iter_open_container(aIter, DBUS_TYPE_ARRAY,
- array_signature, &arrayIter))
+ int dbustype = dbus_signature_iter_get_current_type(&aChildSigIter);
+
+ if (typesMatch(type, dbustype))
{
- addArrayDataToIter(data_ptr, count, type, &arrayIter, &aChildSigIter);
+ BDBLOG(("*** Yay, types match!\n"));
+
+ DBusMessageIter arrayIter;
+ if (dbus_message_iter_open_container(aIter, DBUS_TYPE_ARRAY,
+ array_signature, &arrayIter))
+ {
+ addArrayDataToIter(data_ptr, 0, count, type,
+ &arrayIter, &aChildSigIter);
+ dbus_message_iter_close_container(aIter, &arrayIter);
+ }
+ nsMemory::Free(data_ptr);
+ } else {
+ BDBLOG(("*** Bummer, types don't match so we'll need to iterate\n"));
+
+ DBusMessageIter arrayIter;
+ dbus_message_iter_open_container(aIter, DBUS_TYPE_ARRAY,
+ array_signature, &arrayIter);
+
+ /* Seems stupid not to be able to iterate over the values as
+ * nsIVariants directly, but no API to that effect seems to be
+ * available...
+ */
+ for (int i = 0; i < count; i++)
+ {
+ nsCOMPtr<nsIWritableVariant> variant = do_CreateInstance("@mozilla.org/variant;1");
+
+ switch (type)
+ {
+#define SET_INT(bits) \
+ case nsIDataType::VTYPE_INT ## bits: \
+ variant->SetAsInt ## bits(*(((PRInt ## bits*)data_ptr)+i)); \
+ break; \
+ case nsIDataType::VTYPE_UINT ## bits: \
+ variant->SetAsUint ## bits(*(((PRUint ## bits*)data_ptr)+i)); \
+ break;
+ SET_INT(16)
+ SET_INT(32)
+ SET_INT(64)
+ default:
+ BDBLOG(("*** No conversion from %i to %c\n", type, dbustype));
+ break;
+ }
+
+ addVariantToIter(variant, &arrayIter, &aChildSigIter);
+ }
+
dbus_message_iter_close_container(aIter, &arrayIter);
+ nsMemory::Free(data_ptr);
}
- nsMemory::Free(data_ptr);
}
}
else if (element_type == DBUS_TYPE_STRUCT)
}
}
-void addArrayDataToIter(void *data_ptr, PRUint32 count, PRUint16 type, DBusMessageIter *aIter, DBusSignatureIter *aSigIter)
+void addArrayDataToIter(void *data_ptr, PRUint32 start, PRUint32 count, PRUint16 type, DBusMessageIter *aIter, DBusSignatureIter *aSigIter)
{
int aDBusType = dbus_signature_iter_get_current_type(aSigIter);
BDBLOG(("addArrayDataToIter: appending %d elements of type %d '%c'\n", count, type, aDBusType));
switch (type)
{
#define ADD_DATA \
- for (int i = 0; i < count; i++) \
+ for (int i = start; i < count; i++) \
dbus_message_iter_append_basic(aIter, aDBusType, data+i)
case nsIDataType::VTYPE_INT8:
case nsIDataType::VTYPE_UINT8:
case nsIDataType::VTYPE_WCHAR_STR:
{
PRUnichar **data = (PRUnichar **)data_ptr;
- for (int i = 0; i < count; i++)
+ for (int i = start; i < count; i++)
{
const char *val_ptr;
nsCAutoString val = NS_ConvertUTF16toUTF8(data[i]);
case nsIDataType::VTYPE_INTERFACE_IS:
{
nsISupports **data = (nsISupports **)data_ptr;
- for (int i = 0; i < count; i++)
+ for (int i = start; i < count; i++)
{
nsCOMPtr<nsIVariant> data_variant = do_QueryInterface(data[i]);
if (data_variant)
int dbusType = dbus_signature_iter_get_current_type(aSigIter);
- BDBLOG(("%s(%c, %s)\n", __FUNCTION__, dbusType,
- dbus_signature_iter_get_signature(aSigIter)));
+ BDBLOG(("%s(%s, %c, %s)\n", __FUNCTION__,
+ JS_GetTypeName(cx, JS_TypeOfValue(cx, *aValue)),
+ dbusType, dbus_signature_iter_get_signature(aSigIter)));
// Using the expected type instead of the actual allows autoconversion
switch (dbusType)
if (JS_ValueToNumber(cx, *aValue, &d))
{
+ BDBLOG(("%s(%f)\n", __FUNCTION__, d));
dbus_message_iter_append_basic(aIter, dbusType, &d);
}
else
{
- BDBLOG(("%s(): Could not fetch boolean from jsvalue\n", __FUNCTION__));
+ BDBLOG(("%s(): Could not fetch number from jsvalue\n", __FUNCTION__));
}
break;
{
if (JSVAL_IS_OBJECT(*aValue) && JS_IsArrayObject(cx, JSVAL_TO_OBJECT(*aValue)))
{
- JSIdArray *props = JS_Enumerate(cx, JSVAL_TO_OBJECT(*aValue));
- if (props)
- {
- BDBLOG((" got JSIdArray\n"));
+ // Arrays are simply converted to variants and pushed to the
+ // variant code path
+ nsresult rv;
+ nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
+ if(NS_FAILED(rv))
+ return;
+ BDBLOG((" got nsIXPConnect\n"));
- // Open container
- DBusSignatureIter arraySigIter;
- dbus_signature_iter_recurse(aSigIter, &arraySigIter);
- char *array_sig = dbus_signature_iter_get_signature(&arraySigIter);
-
- DBusMessageIter arrayIter;
- dbus_message_iter_open_container(aIter, DBUS_TYPE_ARRAY,
- array_sig, &arrayIter);
- dbus_free(array_sig);
-
- for (int p = 0; p < props->length; p++)
- {
- int type = dbus_signature_iter_get_current_type(&arraySigIter);
- jsval propname;
- JS_IdToValue(cx, props->vector[p], &propname);
-
- jsval propvalue;
- JSString *prop_string = JS_ValueToString(cx, propname);
- if (JS_LookupUCProperty(cx,
- JSVAL_TO_OBJECT(*aValue),
- JS_GetStringChars(prop_string),
- JS_GetStringLength(prop_string),
- &propvalue) == JS_TRUE)
- {
- addJSValueToIter(cx, &propvalue, &arrayIter, &arraySigIter);
- } else {
- break;
- }
-
- dbus_signature_iter_next(&arraySigIter);
- }
-
- dbus_message_iter_close_container(aIter, &arrayIter);
- JS_DestroyIdArray(cx, props);
- }
+ nsIVariant *var = nsnull;
+ nsresult rs = xpc->JSToVariant(cx, *aValue, &var);
+ NS_ENSURE_SUCCESS(rs, );
+
+ addVariantToIter(var, aIter, aSigIter);
}
break;
void getJSValueFromIter(JSContext* cx, DBusMessageIter *aIter, int aDBusType, jsval *v)
{
+ BDBLOG(("%s(%c)\n", __FUNCTION__, aDBusType));
+
+
switch (aDBusType)
{
case DBUS_TYPE_STRING:
case DBUS_TYPE_UINT32:
case DBUS_TYPE_INT64:
case DBUS_TYPE_UINT64:
- case DBUS_TYPE_DOUBLE:
{
dbus_uint64_t val = 0;
dbus_message_iter_get_basic(aIter, &val);
if (!JS_NewNumberValue(cx, (jsdouble)val, v))
{
- printf("%s: Number conversion from %c failed\n", __FUNCTION__,
- aDBusType);
+ BDBLOG(("%s: Number conversion from %c failed\n", __FUNCTION__,
+ aDBusType));
+ }
+ break;
+ }
+ case DBUS_TYPE_DOUBLE:
+ {
+ jsdouble val = 0.0;
+ dbus_message_iter_get_basic(aIter, &val);
+ if (!JS_NewNumberValue(cx, val, v))
+ {
+ BDBLOG(("%s: Number conversion from %c failed\n", __FUNCTION__,
+ aDBusType));
}
break;
}
case DBUS_TYPE_ARRAY:
{
// FIXME: implement!
-/*
+ // FIXME: Dicts
+
nsTArray<jsval> elems;
// recurse to container
+ DBusMessageIter arrayIter;
+ dbus_message_iter_recurse(aIter, &arrayIter);
// iterate over array elements
do
{
- getJSValueFromIter
+ jsval cv;
+ BDBLOG(("arg type: %c\n", dbus_message_iter_get_arg_type(&arrayIter)));
+ getJSValueFromIter(cx,
+ &arrayIter,
+ dbus_message_iter_get_arg_type(&arrayIter),
+ &cv);
+ elems.AppendElement(cv);
- } while (iter_next);
+ } while (dbus_message_iter_next(&arrayIter));
// Create an Array object with the elements
- JSObject *array = JS_NewArrayObject(cx, 0, NULL);
-*/
+ JSObject *array = JS_NewArrayObject(cx, elems.Length(), elems.Elements());
+ *v = OBJECT_TO_JSVAL(array);
break;
}
case DBUS_TYPE_STRUCT: