Skip to content

Commit 8f2c8e4

Browse files
author
Greg Kubisa
committed
STBPLATFORM-139: Implement passing any value to DBus methods, which expect variant.
1 parent 47dff63 commit 8f2c8e4

File tree

1 file changed

+123
-29
lines changed

1 file changed

+123
-29
lines changed

src/ndbus-utils.cc

+123-29
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,112 @@ NDbusExtractMessageArgs (DBusMessageIter *reply_iter) {
184184
return scope.Close(ret);
185185
}
186186

187+
/**
188+
* Creates a signature string for parameters of type "variant". This string will
189+
* become a part of the parameter.
190+
*
191+
* @param value variant value for which to generate the signature
192+
* @param status status of the operation, eg. SUCCESS, OF_MEMORY, etc
193+
* @param buffer private - do NOT use! Memory where the signature will be stored.
194+
* @param index private - do NOT use! The current position within the buffer, when signature is created.
195+
* @return the generated signature or NULL on error. Use g_free to release the signature after use.
196+
*/
197+
static char*
198+
NDbusCreateSignatureForVariant(Local<Value> value, gint &status, gchar* buffer, gint &index) {
199+
// allocate memory for the signature, if necessary
200+
gboolean cleanUp = FALSE;
201+
if (buffer == NULL) {
202+
// fill up with zeros, so that we'll be able to construct signature at the beginning
203+
// of the buffer and the signature will always be a NULL terminated string.
204+
buffer = g_try_new0(gchar, DBUS_MAXIMUM_SIGNATURE_LENGTH);
205+
if(buffer == NULL) {
206+
status = OUT_OF_MEMORY;
207+
return NULL;
208+
}
209+
index = 0; // just in case
210+
cleanUp = TRUE; // in case of error, we'll have to release memory
211+
}
212+
213+
if (value->IsArray()) {
214+
// make sure the signature is not too long. We'll need at least 2 characters for array:
215+
// 1 char for array and 1 for the type of elements
216+
if (index + 2 > DBUS_MAXIMUM_SIGNATURE_LENGTH - 1) {
217+
status = OUT_OF_MEMORY;
218+
if(cleanUp) {
219+
g_free(buffer);
220+
}
221+
return NULL;
222+
}
223+
224+
Local<Array> array = Local<Array>::Cast(value);
225+
buffer[index++] = DBUS_TYPE_ARRAY;
226+
if (array->Length()) {
227+
NDbusCreateSignatureForVariant(array->Get(0), status, buffer, index);
228+
} else {
229+
// array is empty, so we cannot infer the type of elements - we'll just use a string.
230+
buffer[index++] = DBUS_TYPE_STRING;
231+
}
232+
} else if(value->IsObject()) {
233+
// make sure the signature is not too long. We'll need at least 5 characters for a map:
234+
// 1 char for array, 2 for brackets, 1 for key and 1 for value
235+
if (index + 5 > DBUS_MAXIMUM_SIGNATURE_LENGTH - 1) {
236+
status = OUT_OF_MEMORY;
237+
if(cleanUp) {
238+
g_free(buffer);
239+
}
240+
return NULL;
241+
}
242+
Local<Object> obj = Local<Object>::Cast(value);
243+
Local<Array> properties = obj->GetOwnPropertyNames();
244+
buffer[index++] = 'a';
245+
buffer[index++] = '{';
246+
buffer[index++] = 's'; // keys of objects are strings in JS.
247+
if(properties->Length()) {
248+
NDbusCreateSignatureForVariant(obj->Get(properties->Get(0)), status, buffer, index);
249+
// we do not know how many characters did the method above added, so we have
250+
// to check, if we can still add the closing bracket
251+
if (index + 1 > DBUS_MAXIMUM_SIGNATURE_LENGTH - 1) {
252+
status = OUT_OF_MEMORY;
253+
if(cleanUp) {
254+
g_free(buffer);
255+
}
256+
return NULL;
257+
}
258+
} else {
259+
buffer[index++] = 's'; // no properties in this object, so we'll assume values are strings
260+
}
261+
buffer[index++] = '}';
262+
} else {
263+
// make sure the signature is not too long
264+
if (index + 1 > DBUS_MAXIMUM_SIGNATURE_LENGTH - 1) {
265+
status = OUT_OF_MEMORY;
266+
if(cleanUp) {
267+
g_free(buffer);
268+
}
269+
return NULL;
270+
}
271+
272+
if (value->IsString()) {
273+
buffer[index++] = DBUS_TYPE_STRING;
274+
} else if (value->IsInt32()) {
275+
buffer[index++] = DBUS_TYPE_INT32;
276+
} else if (value->IsUint32()) {
277+
buffer[index++] = DBUS_TYPE_UINT32;
278+
} else if (value->IsNumber()) {
279+
buffer[index++] = DBUS_TYPE_DOUBLE;
280+
} else if (value->IsBoolean()) {
281+
buffer[index++] = DBUS_TYPE_BOOLEAN;
282+
} else {
283+
status = TYPE_NOT_SUPPORTED;
284+
if(cleanUp) {
285+
g_free(buffer);
286+
}
287+
return NULL;
288+
}
289+
}
290+
return buffer;
291+
}
292+
187293
static gint
188294
NDbusMessageAppendArgsReal (DBusMessageIter * iter,
189295
const gchar *signature, Local<Value> value) {
@@ -367,37 +473,25 @@ NDbusMessageAppendArgsReal (DBusMessageIter * iter,
367473
case DBUS_TYPE_VARIANT:
368474
{
369475
DBusMessageIter subiter;
370-
gchar vsignature[2];
371-
vsignature[0] = 0;
372-
373-
if (value->IsString()) {
374-
vsignature[0] = DBUS_TYPE_STRING;
375-
vsignature[1] = '\0';
376-
} else if (value->IsInt32()) {
377-
vsignature[0] = DBUS_TYPE_INT32;
378-
vsignature[1] = '\0';
379-
} else if (value->IsBoolean()) {
380-
vsignature[0] = DBUS_TYPE_BOOLEAN;
381-
vsignature[1] = '\0';
476+
gint status = SUCCESS;
477+
gint index = 0;
478+
// this method should not require the last 2 params (NULL and index)
479+
gchar* vsignature = NDbusCreateSignatureForVariant(value, status, NULL, index);
480+
if(status != SUCCESS) {
481+
return status;
382482
}
383483

384-
if (vsignature[0]) {
385-
if (!dbus_message_iter_open_container
386-
(iter, DBUS_TYPE_VARIANT, vsignature, &subiter)) {
387-
g_free(vsignature);
388-
return OUT_OF_MEMORY;
389-
}
390-
391-
gint status = NDbusMessageAppendArgsReal(&subiter,
392-
vsignature, value);
393-
if (status != SUCCESS) {
394-
g_free(vsignature);
395-
return status;
396-
}
397-
398-
dbus_message_iter_close_container(iter, &subiter);
399-
} else
400-
return TYPE_MISMATCH;
484+
if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, vsignature, &subiter)) {
485+
g_free(vsignature);
486+
return OUT_OF_MEMORY;
487+
}
488+
status = NDbusMessageAppendArgsReal(&subiter, vsignature, value);
489+
if (status != SUCCESS) {
490+
g_free(vsignature);
491+
return status;
492+
}
493+
g_free(vsignature);
494+
dbus_message_iter_close_container(iter, &subiter);
401495
break;
402496
}
403497
default:

0 commit comments

Comments
 (0)