@@ -184,6 +184,112 @@ NDbusExtractMessageArgs (DBusMessageIter *reply_iter) {
184
184
return scope.Close (ret);
185
185
}
186
186
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
+
187
293
static gint
188
294
NDbusMessageAppendArgsReal (DBusMessageIter * iter,
189
295
const gchar *signature, Local<Value> value) {
@@ -367,37 +473,25 @@ NDbusMessageAppendArgsReal (DBusMessageIter * iter,
367
473
case DBUS_TYPE_VARIANT:
368
474
{
369
475
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;
382
482
}
383
483
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);
401
495
break ;
402
496
}
403
497
default :
0 commit comments