Author: mvidner
Date: Wed Jul 1 16:37:56 2009
New Revision: 57826
URL: http://svn.opensuse.org/viewcvs/yast?rev=57826&view=rev
Log:
Enhanced DBus -> YCP value conversion by considering
also the expected YCP type.
Otherwise it is impossible to tell whether an empty array
should become an empty map or an empty list (bnc#516492).
Not finished yet:
- many test cases are missing
- errors are only logged but not sent over DBus
Modified:
branches/tmp/mvidner/core-dbus-values/dbus/SCR_service/DBusServer.cc
branches/tmp/mvidner/core-dbus-values/dbus/namespace_service/src/DBusModulesServer.cc
branches/tmp/mvidner/core-dbus-values/dbus/namespace_service/src/DBusModulesServer.h
branches/tmp/mvidner/core-dbus-values/dbus/namespace_service/testsuite/t2
branches/tmp/mvidner/core-dbus-values/dbus/namespace_service/testsuite/test_all
branches/tmp/mvidner/core-dbus-values/libscr/src/SCR.cc
branches/tmp/mvidner/core-dbus-values/liby2dbus/src/DBusMsg.cc
branches/tmp/mvidner/core-dbus-values/liby2dbus/src/DBusMsg.h
branches/tmp/mvidner/core-dbus-values/liby2dbus/src/DBusServerBase.h
Modified: branches/tmp/mvidner/core-dbus-values/dbus/SCR_service/DBusServer.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/tmp/mvidner/core-dbus-values/dbus/SCR_service/DBusServer.cc?rev=57826&r1=57825&r2=57826&view=diff
==============================================================================
--- branches/tmp/mvidner/core-dbus-values/dbus/SCR_service/DBusServer.cc (original)
+++ branches/tmp/mvidner/core-dbus-values/dbus/SCR_service/DBusServer.cc Wed Jul 1 16:37:56 2009
@@ -118,7 +118,7 @@
}
else
{
- arg0 = request.getYCPValue(0);
+ arg0 = request.getYCPValue(0, Type::Path);
if (arg0.isNull() || !arg0->isPath())
{
@@ -141,8 +141,8 @@
if (check_ok)
{
- YCPValue arg = request.getYCPValue(1);
- YCPValue opt = request.getYCPValue(2);
+ YCPValue arg = request.getYCPValue(1, Type::Unspec);
+ YCPValue opt = request.getYCPValue(2, Type::Unspec);
std::string caller(request.sender());
@@ -205,9 +205,9 @@
ret.push_back(action_id);
- YCPValue path = msg.getYCPValue(0);
- YCPValue arg = msg.getYCPValue(1);
- YCPValue opt = msg.getYCPValue(2);
+ YCPValue path = msg.getYCPValue(0, Type::Path);
+ YCPValue arg = msg.getYCPValue(1, Type::Unspec);
+ YCPValue opt = msg.getYCPValue(2, Type::Unspec);
std::string path_str, arg_str, opt_str;
Modified: branches/tmp/mvidner/core-dbus-values/dbus/namespace_service/src/DBusModulesServer.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/tmp/mvidner/core-dbus-values/dbus/namespace_service/src/DBusModulesServer.cc?rev=57826&r1=57825&r2=57826&view=diff
==============================================================================
--- branches/tmp/mvidner/core-dbus-values/dbus/namespace_service/src/DBusModulesServer.cc (original)
+++ branches/tmp/mvidner/core-dbus-values/dbus/namespace_service/src/DBusModulesServer.cc Wed Jul 1 16:37:56 2009
@@ -433,7 +433,8 @@
while(index < reqarg)
{
- YCPValue arg = request.getYCPValue(index);
+ constTypePtr argtype(fptr->parameterType(index));
+ YCPValue arg = request.getYCPValue(index, argtype);
if (arg.isNull())
{
@@ -443,8 +444,6 @@
}
// check the data type compatibility
- constTypePtr argtype(fptr->parameterType(index));
-
if (argtype->matchvalue(arg) < 0)
{
if (interface == YAST_DBUS_RAW_INTERFACE)
@@ -490,6 +489,7 @@
}
else
{
+ // FIXME should be a dbus error
y2error("Wrong parameters to function %s::%s", object.c_str(), method.c_str());
}
}
@@ -504,13 +504,14 @@
if (!found)
{
+// see also DBusServerBase::unknownRequest
y2internal("Function %s::%s was not found although it was registered", object.c_str(), method.c_str());
string msg = "Method '"+ interface + "." + method + "' "
"on object '" + object + "' doesn't exist";
// anyway, why didnt dbus itself cry?
reply.createError(request, // in reply to
msg,
- "org.freedesktop.DBus.Error.UnknownMethod");
+ DBUS_ERROR_UNKNOWN_METHOD);
return reply;
}
@@ -564,7 +565,7 @@
{
if (request.arguments() == 1)
{
- YCPValue arg = request.getYCPValue(0);
+ YCPValue arg = request.getYCPValue(0, Type::String);
if (arg.isNull())
{
Modified: branches/tmp/mvidner/core-dbus-values/dbus/namespace_service/src/DBusModulesServer.h
URL: http://svn.opensuse.org/viewcvs/yast/branches/tmp/mvidner/core-dbus-values/dbus/namespace_service/src/DBusModulesServer.h?rev=57826&r1=57825&r2=57826&view=diff
==============================================================================
--- branches/tmp/mvidner/core-dbus-values/dbus/namespace_service/src/DBusModulesServer.h (original)
+++ branches/tmp/mvidner/core-dbus-values/dbus/namespace_service/src/DBusModulesServer.h Wed Jul 1 16:37:56 2009
@@ -35,6 +35,7 @@
virtual actionList createActionId(const DBusMsg &msg);
// handle unknown requests
+ // Tries to autoimport and retry
virtual DBusMsg unknownRequest(const DBusMsg &request);
private:
Modified: branches/tmp/mvidner/core-dbus-values/dbus/namespace_service/testsuite/t2
URL: http://svn.opensuse.org/viewcvs/yast/branches/tmp/mvidner/core-dbus-values/dbus/namespace_service/testsuite/t2?rev=57826&r1=57825&r2=57826&view=diff
==============================================================================
--- branches/tmp/mvidner/core-dbus-values/dbus/namespace_service/testsuite/t2 (original)
+++ branches/tmp/mvidner/core-dbus-values/dbus/namespace_service/testsuite/t2 Wed Jul 1 16:37:56 2009
@@ -8,7 +8,7 @@
YT = dbus.Interface(T_o, 'org.opensuse.YaST.YCPValues')
yp = (False, "map", dbus.Dictionary(signature="sv", variant_level=1))
yrp = YT.ParamMap(yp)
-print yrp
+print "Explicit returned:", yrp
assert yrp[0] == False
assert yrp[1] == "map"
rp = yrp[2]
@@ -20,8 +20,6 @@
# p = {} # ValueError: Unable to guess signature from an empty dict
p = dbus.Dictionary(signature="sv")
rp = T.ParamMap(p)
-print rp
+print "Implicit returned:", rp
assert isinstance(rp, dict)
assert len(rp.values()) == 0
-
-# T.NoSuchMethod() # TODO it does not throw!
Modified: branches/tmp/mvidner/core-dbus-values/dbus/namespace_service/testsuite/test_all
URL: http://svn.opensuse.org/viewcvs/yast/branches/tmp/mvidner/core-dbus-values/dbus/namespace_service/testsuite/test_all?rev=57826&r1=57825&r2=57826&view=diff
==============================================================================
--- branches/tmp/mvidner/core-dbus-values/dbus/namespace_service/testsuite/test_all (original)
+++ branches/tmp/mvidner/core-dbus-values/dbus/namespace_service/testsuite/test_all Wed Jul 1 16:37:56 2009
@@ -1,14 +1,21 @@
#! /bin/sh
# run all applicable test cases with proper setup
-# $0
+# $0 [-a: all, even failing]
# $0 ./a_single_testcase
-: ${CASES:=$@}
-# : ${CASES:=./t?} # t2 fails. also, it requires python
- : ${CASES:=./t1}
-
+if [ "$1" = "" ]; then
+ # some(most) of them require python
+ #: ${CASES:=./t1}
+ : ${CASES:=./t[1235]*}
+elif [ "$1" = "-a" ]; then
+ : ${CASES:=./t? ./t*-*}
+else
+ : ${CASES:=$@}
+fi
+CASES_A=($CASES) # make array
+CASES_A=(${CASES_A[@]/*~/}) # exclude backup files
# load the modules from the current directory
export Y2DIR=.
./test_server \
../src/yast_modules_dbus_server --disable-timer --test TEST \
-- \
- $CASES
+ ${CASES_A[@]}
Modified: branches/tmp/mvidner/core-dbus-values/libscr/src/SCR.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/tmp/mvidner/core-dbus-values/libscr/src/SCR.cc?rev=57826&r1=57825&r2=57826&view=diff
==============================================================================
--- branches/tmp/mvidner/core-dbus-values/libscr/src/SCR.cc (original)
+++ branches/tmp/mvidner/core-dbus-values/libscr/src/SCR.cc Wed Jul 1 16:37:56 2009
@@ -83,7 +83,7 @@
y2debug("Received reply type: %d", reply.type());
// return the first argument from the reply
- YCPValue ret = reply.getYCPValue(0);
+ YCPValue ret = reply.getYCPValue(0, Type::Unspec);
// validate the reply (check for exceptions)
if (reply.type() != DBUS_MESSAGE_TYPE_METHOD_RETURN)
Modified: branches/tmp/mvidner/core-dbus-values/liby2dbus/src/DBusMsg.cc
URL: http://svn.opensuse.org/viewcvs/yast/branches/tmp/mvidner/core-dbus-values/liby2dbus/src/DBusMsg.cc?rev=57826&r1=57825&r2=57826&view=diff
==============================================================================
--- branches/tmp/mvidner/core-dbus-values/liby2dbus/src/DBusMsg.cc (original)
+++ branches/tmp/mvidner/core-dbus-values/liby2dbus/src/DBusMsg.cc Wed Jul 1 16:37:56 2009
@@ -1,4 +1,3 @@
-
/*
DBusMsg
@@ -662,265 +661,356 @@
}
-YCPValue DBusMsg::getYCPValueRaw(DBusMessageIter *it, const std::string &ycp_type) const
+// returns NULL if "it" does not point to a string
+const char * DBusMsg::getString(DBusMessageIter *it) const
{
- YCPValue ret;
+ const char *s = NULL;
+ if (dbus_message_iter_get_arg_type (it) == DBUS_TYPE_STRING)
+ {
+ dbus_message_iter_get_basic(it, &s);
+ }
+ return s;
+}
- int type = dbus_message_iter_get_arg_type(it);
+// "it" is the inside iterator
+YCPList DBusMsg::getYCPValueList(DBusMessageIter *it, constTypePtr valuetype) const
+{
+ YCPList lst;
- // TODO support more types
- if (type == DBUS_TYPE_BOOLEAN)
+ while (dbus_message_iter_get_arg_type (it) != DBUS_TYPE_INVALID)
{
- bool b;
- dbus_message_iter_get_basic(it, &b);
- ret = YCPBoolean(b);
+ // FIXME this can fail
+ YCPValue list_val = getYCPValue(it, valuetype);
+ lst->add(list_val);
+
+ dbus_message_iter_next(it);
}
- else if (type == DBUS_TYPE_STRING)
- {
- const char *s;
- dbus_message_iter_get_basic(it, &s);
+ return lst;
+}
- static const char* block_prefix = "block ";
- static const int block_prefix_len = ::strlen(block_prefix);
+// "it" is the inside iterator
+YCPMap DBusMsg::getYCPValueMap(DBusMessageIter *it, constTypePtr keytype, constTypePtr valuetype) const
+{
+ YCPMap map;
- // use ycp_type to return the correct type
- if (ycp_type.empty() || ycp_type == "string")
- ret = YCPString(s);
- else if (ycp_type == "symbol")
- ret = YCPSymbol(s);
- else if (ycp_type == "path")
- ret = YCPPath(s);
- else if (std::string(ycp_type, 0, block_prefix_len) == block_prefix)
+ while (dbus_message_iter_get_arg_type (it) != DBUS_TYPE_INVALID)
+ {
+ // is it a map or a list?
+ if (dbus_message_iter_get_arg_type(it) == DBUS_TYPE_DICT_ENTRY)
{
- y2debug("Found YCP block");
+ DBusMessageIter mapit;
+ dbus_message_iter_recurse(it, &mapit);
- if (s == NULL || *s == '\0')
- {
- y2warning("The code block is empty");
- ret = YCPVoid();
- }
- else
- {
- // parse the string, recreate the YCPBlock again
- Parser parser(s);
- parser.setBuffered();
- YCodePtr p = parser.parse();
- YCPValue contents = YCPNull ();
-
- if (!p)
- {
- y2error("Parse error in YCP code: %s", s);
- }
- else
- {
- if (p->isBlock ())
- {
- contents = YCPCode (p);
- }
- else
- {
- contents = p->evaluate (true);
- }
- }
+ // DICT keys cannot be structs, skip Bsv
+ YCPValue key = getYCPValueRawType(&mapit, keytype);
- ret = !contents.isNull() ? contents : YCPVoid();
- }
+ dbus_message_iter_next(&mapit);
+
+ // read the value
+ YCPValue val = getYCPValue(&mapit, valuetype);
+
+ map->add(key, val);
}
- else
+ // else FIXME how to signal error
+
+ dbus_message_iter_next(it);
+ }
+ return map;
+}
+
+// returns YCPNull without an error if "it" does not point to an integer/byte
+YCPValue DBusMsg::getYCPValueInteger(DBusMessageIter *it) const
+{
+ int type = dbus_message_iter_get_arg_type(it);
+ YCPValue ret;
+
+ switch (type) {
+ case DBUS_TYPE_INT64:
{
- y2warning("Unknown STRING data, returning as YCPString");
- // default is YCPString
- ret = YCPString(s);
+ dbus_int64_t i;
+ dbus_message_iter_get_basic(it, &i);
+ ret = YCPInteger(i);
+ break;
+ }
+ case DBUS_TYPE_UINT64:
+ {
+ // warning: YCPInteger is signed!
+ dbus_uint64_t i;
+ dbus_message_iter_get_basic(it, &i);
+ ret = YCPInteger(i);
+ break;
+ }
+ case DBUS_TYPE_INT32:
+ {
+ dbus_int32_t i;
+ dbus_message_iter_get_basic(it, &i);
+ ret = YCPInteger(i);
+ break;
+ }
+ case DBUS_TYPE_UINT32:
+ {
+ dbus_uint32_t i;
+ dbus_message_iter_get_basic(it, &i);
+ ret = YCPInteger(i);
+ break;
+ }
+ case DBUS_TYPE_INT16:
+ {
+ dbus_int16_t i;
+ dbus_message_iter_get_basic(it, &i);
+ ret = YCPInteger(i);
+ break;
+ }
+ case DBUS_TYPE_UINT16:
+ {
+ dbus_uint16_t i;
+ dbus_message_iter_get_basic(it, &i);
+ ret = YCPInteger(i);
+ break;
+ }
+ case DBUS_TYPE_BYTE:
+ {
+ unsigned char i;
+ dbus_message_iter_get_basic(it, &i);
+ ret = YCPInteger(i);
+ break;
}
}
- else if (type == DBUS_TYPE_ARRAY)
- {
- DBusMessageIter sub;
- dbus_message_iter_recurse(it, &sub);
+ return ret;
+}
- // DBUS_TYPE_ARRAY is used for YCPList and YCPMap
- if (ycp_type == "list")
- {
- y2debug("Found an YCPList container");
- YCPList lst;
+// here ycptype is NOT Type::Unspec
+YCPValue DBusMsg::getYCPValueRawType(DBusMessageIter *it, constTypePtr ycptype) const
+{
+ if (ycptype->isAny())
+ return getYCPValueRawAny(it);
- while (dbus_message_iter_get_arg_type (&sub) != DBUS_TYPE_INVALID)
- {
- YCPValue list_val = getYCPValue(&sub);
- lst->add(list_val);
+ YCPValue ret;
- dbus_message_iter_next(&sub);
- }
+ int type = dbus_message_iter_get_arg_type(it);
+ bool mismatch = true;
- ret = lst;
+ if (ycptype->isBoolean())
+ {
+ if (type == DBUS_TYPE_BOOLEAN)
+ {
+ bool b;
+ dbus_message_iter_get_basic(it, &b);
+ ret = YCPBoolean(b);
+ mismatch = false;
}
- else if (ycp_type == "map")
+ }
+ else if (ycptype->isInteger())
+ {
+ ret = getYCPValueInteger(it);
+ mismatch = ret.isNull();
+ }
+ else if (ycptype->isFloat())
+ {
+ if (type == DBUS_TYPE_DOUBLE)
{
- y2debug("Found an YCPMap container");
- YCPMap map;
-
- while (dbus_message_iter_get_arg_type (&sub) != DBUS_TYPE_INVALID)
- {
- // is it a map or a list?
- if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY)
- {
- DBusMessageIter mapit;
- dbus_message_iter_recurse(&sub, &mapit);
-
- // read the key without the header
- YCPValue key = getYCPValueRaw(&mapit);
+ double d;
+ dbus_message_iter_get_basic(it, &d);
+ ret = YCPFloat(d);
+ mismatch = false;
+ }
+ }
+ else if (ycptype->isList())
+ {
+ // DBUS_TYPE_ARRAY is used for YCPList and YCPMap
+ // TODO sending a dict where a list is expected will confusingly complain about value type mismatch
+ if (type == DBUS_TYPE_ARRAY)
+ {
+ DBusMessageIter sub;
+ dbus_message_iter_recurse(it, &sub);
- dbus_message_iter_next(&mapit);
+ constListTypePtr list_type = (constListTypePtr) ycptype;
+ constTypePtr valuetype = list_type->type();
- // read the value
- YCPValue val = getYCPValue(&mapit);
+ // FIXME this can fail
+ ret = getYCPValueList(&sub, valuetype);
+ mismatch = false;
+ }
+ }
+ else if (ycptype->isMap())
+ {
+ if (type == DBUS_TYPE_ARRAY)
+ {
+ DBusMessageIter sub;
+ dbus_message_iter_recurse(it, &sub);
- map->add(key, val);
- }
+ constMapTypePtr map_type = (constMapTypePtr) ycptype;
+ constTypePtr keytype = map_type->keytype();
+ constTypePtr valuetype = map_type->valuetype();
- dbus_message_iter_next(&sub);
- }
-
- ret = map;
+ ret = getYCPValueMap(&sub, keytype, valuetype);
+ mismatch = false;
}
- else if (ycp_type == "term")
+ }
+ else if (ycptype->isTerm())
+ {
+ // array with first item being the name
+ if (type == DBUS_TYPE_ARRAY)
{
- y2debug("Found an YCPTerm container");
+ DBusMessageIter sub;
+ dbus_message_iter_recurse(it, &sub);
- YCPList term_list;
std::string term_name;
+ YCPList term_list;
- int index = 0;
- while (dbus_message_iter_get_arg_type (&sub) != DBUS_TYPE_INVALID)
+ if (dbus_message_iter_get_arg_type (&sub) != DBUS_TYPE_INVALID)
{
- YCPValue list_val = getYCPValue(&sub);
-
- if (index == 0)
+ YCPValue ytn = getYCPValue(&sub, Type::String);
+ if (!ytn.isNull() && ytn->isString())
{
- if (!list_val.isNull() && list_val->isString())
- {
- term_name = list_val->asString()->value();
- }
- else
- {
- y2error("Expecting string (term name) in the list");
- return YCPVoid();
- }
+ term_name = ytn->asString()->value();
+ dbus_message_iter_next(&sub);
+
+ term_list = getYCPValueList(&sub, Type::Unspec);
+
+ y2debug("Received TERM: name: %s, list: %s", term_name.c_str(), term_list->toString().c_str());
+
+ ret = YCPTerm(term_name, term_list);
+ mismatch = false;
}
else
{
- term_list->add(list_val);
+ y2error("Expecting string (term name) in the list");
+ return YCPVoid(); // FIXME
}
-
- dbus_message_iter_next(&sub);
- index++;
}
-
- y2debug("Received TERM: name: %s, list: %s", term_name.c_str(), term_list->toString().c_str());
-
- YCPTerm term(term_name, term_list);
- ret = term;
}
- else if (ycp_type.empty())
+ }
+ else if (ycptype->isString())
+ {
+ const char *s = getString(it);
+ if (s != NULL)
{
- y2debug("Reading RAW DBus array");
-
- // is the container a map or a list?
- if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY)
+ ret = YCPString(s);
+ mismatch = false;
+ }
+ }
+ else if (ycptype->isSymbol())
+ {
+ const char *s = getString(it);
+ if (s != NULL)
+ {
+ ret = YCPSymbol(s);
+ mismatch = false;
+ }
+ }
+ else if (ycptype->isPath())
+ {
+ const char *s = getString(it);
+ if (s != NULL)
+ {
+ ret = YCPPath(s);
+ mismatch = false;
+ }
+ }
+ // parsed YCP code, wow.
+ //FIXME does the execution precede auth checks?!
+ else if (ycptype->isBlock())
+ {
+ const char *s = getString(it);
+ if (s != NULL)
+ {
+ if (*s == '\0')
{
- y2debug("Found a map");
-
- YCPMap map;
-
- while (dbus_message_iter_get_arg_type (&sub) != DBUS_TYPE_INVALID)
- {
- // is it a map or a list?
- if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY)
- {
- DBusMessageIter mapit;
- dbus_message_iter_recurse(&sub, &mapit);
-
- // read the key without the header
- YCPValue key = getYCPValueRaw(&mapit);
-
- dbus_message_iter_next(&mapit);
-
- // read the value
- YCPValue val = getYCPValueRaw(&mapit);
-
- map->add(key, val);
- }
-
- dbus_message_iter_next(&sub);
- }
-
- ret = map;
+ y2warning("The code block is empty");
+ ret = YCPVoid();
}
else
{
- y2debug("Found a list");
-
- YCPList lst;
+ // parse the string, recreate the YCPBlock again
+ Parser parser(s);
+ parser.setBuffered();
+ YCodePtr p = parser.parse();
- while (dbus_message_iter_get_arg_type (&sub) != DBUS_TYPE_INVALID)
+ if (!p)
{
- YCPValue list_val = getYCPValue(&sub);
- lst->add(list_val);
-
- dbus_message_iter_next(&sub);
+ y2error("Parse error in YCP code: %s", s);
+ ret = YCPVoid();
+ }
+ else
+ {
+ ret = p->isBlock ()? YCPCode (p): p->evaluate (true);
}
-
- ret = lst;
}
- }
- else
- {
- y2error("Unknown container type for DBUS_TYPE_ARRAY: %s", ycp_type.c_str());
- ret = YCPVoid();
+ mismatch = false;
}
}
- else if (type == DBUS_TYPE_DOUBLE)
- {
- double d;
- dbus_message_iter_get_basic(it, &d);
- ret = YCPFloat(d);
- }
- else if (type == DBUS_TYPE_INT64)
+ else
{
- dbus_int64_t i;
- dbus_message_iter_get_basic(it, &i);
- ret = YCPInteger(i);
+ y2error ("Missing code to convert DBus data to YCP type %s",
+ ycptype->toString().c_str());
}
- else if (type == DBUS_TYPE_UINT64)
+
+ if (mismatch)
{
- // warning: YCPInteger is signed!
- dbus_uint64_t i;
- dbus_message_iter_get_basic(it, &i);
- ret = YCPInteger(i);
+ y2error ("Data mismatch, expecting YCP type %s, got DBus type %c",
+ ycptype->toString().c_str(), (char)type);
}
- else if (type == DBUS_TYPE_INT32)
+
+ return ret;
+}
+
+YCPValue DBusMsg::getYCPValueRawAny(DBusMessageIter *it) const
+{
+ YCPValue ret;
+
+ int type = dbus_message_iter_get_arg_type(it);
+ // TODO support more types
+ if (type == DBUS_TYPE_BOOLEAN)
{
- dbus_int32_t i;
- dbus_message_iter_get_basic(it, &i);
- ret = YCPInteger(i);
+ bool b;
+ dbus_message_iter_get_basic(it, &b);
+ ret = YCPBoolean(b);
}
- else if (type == DBUS_TYPE_UINT32)
+ else if (type == DBUS_TYPE_STRING)
{
- dbus_uint32_t i;
- dbus_message_iter_get_basic(it, &i);
- ret = YCPInteger(i);
+ const char *s;
+ dbus_message_iter_get_basic(it, &s);
+ ret = YCPString(s);
+
}
- else if (type == DBUS_TYPE_INT16)
+ else if (type == DBUS_TYPE_ARRAY)
{
- dbus_int16_t i;
- dbus_message_iter_get_basic(it, &i);
- ret = YCPInteger(i);
+ DBusMessageIter sub;
+ dbus_message_iter_recurse(it, &sub);
+
+ // DBUS_TYPE_ARRAY is used for YCPList and YCPMap
+ y2debug("Reading RAW DBus array");
+
+ // is the container a map or a list?
+ // An empty map is indistinguishable from a list!
+ if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY)
+ {
+ y2debug("Found a map");
+ ret = getYCPValueMap(&sub, Type::Any, Type::Unspec);
+ }
+ else
+ {
+ y2debug("Found a list");
+
+ YCPList lst;
+
+ while (dbus_message_iter_get_arg_type (&sub) != DBUS_TYPE_INVALID)
+ {
+ YCPValue list_val = getYCPValue(&sub, Type::Unspec);
+ lst->add(list_val);
+
+ dbus_message_iter_next(&sub);
+ }
+
+ ret = lst;
+ }
}
- else if (type == DBUS_TYPE_UINT16)
+ else if (type == DBUS_TYPE_DOUBLE)
{
- dbus_uint16_t i;
- dbus_message_iter_get_basic(it, &i);
- ret = YCPInteger(i);
+ double d;
+ dbus_message_iter_get_basic(it, &d);
+ ret = YCPFloat(d);
}
else if (type == DBUS_TYPE_VARIANT)
{
@@ -933,42 +1023,57 @@
// there should be just one value inside the container
if (dbus_message_iter_get_arg_type (&sub) != DBUS_TYPE_INVALID)
{
- val = getYCPValueRaw(&sub);
+ val = getYCPValueRawAny(&sub);
}
-
+ // FIXME YCPNull possible
ret = val;
}
else
{
- y2error("Unsupported DBus type: %d (%c)", type, (char)type);
- ret = YCPVoid();
+ ret = getYCPValueInteger(it);
+ if (ret.isNull())
+ {
+ y2error("Unsupported DBus type: %d (%c)", type, (char)type);
+ ret = YCPVoid();
+ }
}
return ret;
}
-YCPValue DBusMsg::getYCPValue(DBusMessageIter *it) const
+// main getter dispatcher
+YCPValue DBusMsg::getYCPValue(DBusMessageIter *it, constTypePtr ycptype) const
{
int type = dbus_message_iter_get_arg_type(it);
y2debug("Found DBus type: %d (%c)", type, (char)type);
+ YCPValue ret;
if (type != DBUS_TYPE_STRUCT)
{
- YCPValue ret = getYCPValueRaw(it, "");
- if (ret.isNull())
- {
- ret = YCPVoid();
- }
+ if (ycptype->isUnspec())
+ ret = getYCPValueRawAny(it);
+ else
+ ret = getYCPValueRawType(it, ycptype);
- y2milestone("Using RAW dbus value '%s' instead of (bsv) YCPValue structure", ret->toString().c_str());
+// y2milestone("Using RAW dbus value '%s' instead of (bsv) YCPValue structure", ret->toString().c_str());
+ }
+ else
+ ret = getYCPValueBsv(it, ycptype);
- return ret;
+ if (ret.isNull()) // TODO unify
+ {
+ ret = YCPVoid();
}
+ return ret;
+}
+// "it" must point to a struct
+YCPValue DBusMsg::getYCPValueBsv(DBusMessageIter *it, constTypePtr ycptype) const
+{
DBusMessageIter struct_iter;
dbus_message_iter_recurse(it, &struct_iter);
- type = dbus_message_iter_get_arg_type(&struct_iter);
+ int type = dbus_message_iter_get_arg_type(&struct_iter);
bool received_nil = false;
// read the nil flag at the beginning
@@ -987,6 +1092,8 @@
}
else
{
+ // FIXME "response" is wrong, can go both ways.
+ // for params, should throw param dbus error
y2error("Missing nil flag in the response");
return YCPVoid();
}
@@ -994,14 +1101,29 @@
// read the data type in the header
dbus_message_iter_next(&struct_iter);
- std::string ycp_type;
+ constTypePtr vycptype = Type::Unspec;
type = dbus_message_iter_get_arg_type(&struct_iter);
if (type == DBUS_TYPE_STRING)
{
const char *str;
dbus_message_iter_get_basic(&struct_iter, &str);
y2debug("HEADER: type: %s", str);
- ycp_type = str;
+
+ std::string ycp_type = str;
+ if (ycp_type == "string")
+ vycptype = Type::String;
+ else if (ycp_type == "symbol")
+ vycptype = Type::Symbol;
+ else if (ycp_type == "path")
+ vycptype = Type::Path;
+ else if (ycp_type == "list")
+ vycptype = Type::List;
+ else if (ycp_type == "map")
+ vycptype = Type::Map;
+ else if (ycp_type == "block")
+ vycptype = Type::Block;
+ else
+ y2error("Dunno how to translate BSV type %s to YCP type", str);
}
else
{
@@ -1023,12 +1145,13 @@
DBusMessageIter variant_iter;
dbus_message_iter_recurse(&struct_iter, &variant_iter);
- YCPValue ret = getYCPValueRaw(&variant_iter, ycp_type);
+ YCPValue ret = getYCPValueRawType(&variant_iter, vycptype);
return (received_nil) ? YCPVoid() : ret;
}
-YCPValue DBusMsg::getYCPValue(int index) const
+// the public getter: idx
+YCPValue DBusMsg::getYCPValue(int index, constTypePtr ycptype) const
{
YCPValue ret = YCPNull();
@@ -1046,6 +1169,7 @@
int i = 0;
// iterate over the other arguments
+//wasteful API?
while (i < index && dbus_message_iter_next(&it))
{
i++;
@@ -1053,7 +1177,7 @@
if (i == index)
{
- ret = getYCPValue(&it);
+ ret = getYCPValue(&it, ycptype);
}
else
{
Modified: branches/tmp/mvidner/core-dbus-values/liby2dbus/src/DBusMsg.h
URL: http://svn.opensuse.org/viewcvs/yast/branches/tmp/mvidner/core-dbus-values/liby2dbus/src/DBusMsg.h?rev=57826&r1=57825&r2=57826&view=diff
==============================================================================
--- branches/tmp/mvidner/core-dbus-values/liby2dbus/src/DBusMsg.h (original)
+++ branches/tmp/mvidner/core-dbus-values/liby2dbus/src/DBusMsg.h Wed Jul 1 16:37:56 2009
@@ -1,4 +1,3 @@
-
/*
DBusMsg
*/
@@ -12,6 +11,8 @@
#include