Mercurial > projects > dbus-d
comparison dbus-d/dsrc/org/freedesktop/dbus/DBus.d @ 0:a5576806d36d
recreate repository without any libs for lightweight repository
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Sat, 20 Oct 2007 18:07:18 +0200 |
parents | |
children | 7c2c75740370 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:a5576806d36d |
---|---|
1 /* | |
2 * Copyright (C) 2007 Frank Benoit | |
3 * | |
4 * Licensed under the Academic Free License version 2.1 | |
5 * | |
6 * This program is free software; you can redistribute it and/or modify | |
7 * it under the terms of the GNU General Public License as published by | |
8 * the Free Software Foundation; either version 2 of the License, or | |
9 * (at your option) any later version. | |
10 * | |
11 * This program is distributed in the hope that it will be useful, | |
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 * GNU General Public License for more details. | |
15 * | |
16 * You should have received a copy of the GNU General Public License | |
17 * along with this program; if not, write to the Free Software | |
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
19 * | |
20 */ | |
21 module org.freedesktop.dbus.DBus; | |
22 | |
23 import tango.io.Stdout; | |
24 import tango.core.Exception; | |
25 import tango.core.Thread; | |
26 import tango.core.Traits; | |
27 import tango.text.convert.Integer; | |
28 import tango.text.Util; | |
29 | |
30 public import tango.stdc.stringz : fromUtf8z; | |
31 //public import tango.core.Tuple; | |
32 //public import org.freedesktop.dbus.DBusInterface; | |
33 | |
34 import org.freedesktop.dbus.c.Connection; | |
35 import org.freedesktop.dbus.c.Errors; | |
36 import org.freedesktop.dbus.c.Message; | |
37 import org.freedesktop.dbus.c.Bus; | |
38 import org.freedesktop.dbus.c.PendingCall; | |
39 import org.freedesktop.dbus.c.Shared; | |
40 import org.freedesktop.dbus.c.Protocol; | |
41 import org.freedesktop.dbus.c.Types; | |
42 import org.freedesktop.dbus.c.Memory : dbus_free; | |
43 import org.freedesktop.dbus.Struct; | |
44 import org.freedesktop.dbus.Variant; | |
45 | |
46 //version=CD; | |
47 | |
48 typedef char[] DBusObjPath; | |
49 typedef char[] DBusSignature; | |
50 | |
51 private void notImplemented( char[] msg = null ){ | |
52 throw new TracedException( "not yet implemented " ~ msg ); | |
53 } | |
54 | |
55 private void ensure( bool cond, char[][] msg ... ){ | |
56 if( !cond ){ | |
57 char[200] buf; | |
58 char[] formattedMsg = layout( buf, msg ); | |
59 throw new TracedException( "ensure failed: "~formattedMsg ); | |
60 } | |
61 } | |
62 | |
63 private void ensureDBus( dbus_bool_t cond ){ | |
64 if( !cond ){ | |
65 throw new TracedException( "ensureDBus" ); | |
66 } | |
67 } | |
68 | |
69 | |
70 alias DBusHandlerResult | |
71 function( | |
72 DBusConnection* conn, | |
73 DBusMessage* message, | |
74 void* user_data ) | |
75 DBusHandler; | |
76 | |
77 | |
78 char[] [ ClassInfo ] registeredIntrospectionData; | |
79 DBusHandler[ ClassInfo ] registeredHandlers; | |
80 | |
81 public void registerIntrospectionData( ClassInfo ci, char[] data ){ | |
82 registeredIntrospectionData[ ci ] = data; | |
83 } | |
84 public void registerHandler( ClassInfo ci, DBusHandler handler ){ | |
85 registeredHandlers[ ci ] = handler; | |
86 } | |
87 | |
88 public class DBusObjectImpl { | |
89 static uint sInstCounter = 0; | |
90 char[] instName; | |
91 this(){ | |
92 //Stdout.formatln( "DBusObject ctor" ); | |
93 int cnt; | |
94 synchronized{ | |
95 cnt = sInstCounter++; | |
96 } | |
97 instName = '/' ~ replace( this.classinfo.name.dup, '.', '/' ) ~ '/' ~ .toUtf8( cnt ); | |
98 //Stdout.formatln( "DBusObject instname={}", instName ); | |
99 } | |
100 | |
101 public char[] getDBusInstanceName(){ | |
102 return instName; | |
103 } | |
104 | |
105 public char[] Introspect(){ | |
106 char[] res = "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n" | |
107 "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n" | |
108 "<node>\n"; | |
109 bool[ ClassInfo ] all; | |
110 void appendInterfaces( Interface[] intfs ){ | |
111 foreach( intf; intfs ){ | |
112 if( intf.classinfo.interfaces.length > 0 ){ | |
113 appendInterfaces( intf.classinfo.interfaces ); | |
114 } | |
115 all[ intf.classinfo ] = true; | |
116 } | |
117 } | |
118 appendInterfaces( this.classinfo.interfaces ); | |
119 foreach( intf; all.keys ){ | |
120 char[]* intro = intf in registeredIntrospectionData; | |
121 if( intro !is null ){ | |
122 res ~= *intro; | |
123 } | |
124 } | |
125 DBusObjectImpl[] childs = getChildNodes(); | |
126 foreach( child; childs ){ | |
127 res ~= " <node name=\""~child.instName~"\"/>\n"; | |
128 } | |
129 res ~= "</node>\n"; | |
130 //Stdout.formatln( "DBus.d:{} Introspect: {}", __LINE__, res ); | |
131 return res; | |
132 } | |
133 | |
134 public DBusObjectImpl[] getChildNodes(){ | |
135 return null; | |
136 } | |
137 | |
138 private static extern(C) DBusHandlerResult VTableMessageFunction( | |
139 DBusConnection* conn, | |
140 DBusMessage* message, | |
141 void* user_data ) | |
142 { | |
143 char[METHOD_SIG_MAXLENGTH] buf; | |
144 DBusObjectImpl o = cast(DBusObjectImpl)cast(Object)user_data; | |
145 | |
146 // find all interfaces ... | |
147 bool[ ClassInfo ] all; | |
148 void findAllInterfaces( Interface[] intfs ){ | |
149 foreach( intf; intfs ){ | |
150 findAllInterfaces( intf.classinfo.interfaces ); | |
151 all[ intf.classinfo ] = true; | |
152 } | |
153 } | |
154 ClassInfo oci = o.classinfo; | |
155 do{ | |
156 findAllInterfaces( oci.interfaces ); | |
157 oci = oci.base; | |
158 } while( oci !is null ); | |
159 | |
160 // call all existing handlers until message handled | |
161 foreach( intf; all.keys ){ | |
162 DBusHandler* handler = intf in registeredHandlers; | |
163 if( handler !is null ){ | |
164 DBusHandlerResult res = | |
165 (*handler)( conn, message, user_data ); | |
166 if( res == DBusHandlerResult.DBUS_HANDLER_RESULT_HANDLED ){ | |
167 return DBusHandlerResult.DBUS_HANDLER_RESULT_HANDLED; | |
168 } | |
169 } | |
170 } | |
171 return DBusHandlerResult.DBUS_HANDLER_RESULT_NOT_YET_HANDLED; | |
172 } | |
173 | |
174 private static extern(C) void VTableUnregisterFunction( | |
175 DBusConnection *connection, | |
176 void* user_data ) | |
177 { | |
178 DBusObjectImpl o = cast(DBusObjectImpl)cast(Object)user_data; | |
179 objectLocker.remove( o ); | |
180 } | |
181 | |
182 private static DBusObjectPathVTable dbusObjectPathVTable = { | |
183 message_function : & VTableMessageFunction, | |
184 unregister_function : & VTableUnregisterFunction | |
185 }; | |
186 | |
187 public void registerDBusObject( DBusConnection * conn ){ | |
188 ensureDBus( dbus_connection_register_object_path( | |
189 conn, | |
190 XtoUtf8z( getDBusInstanceName() ), | |
191 & dbusObjectPathVTable, | |
192 cast(void*)cast(Object)this )); | |
193 objectLocker[ this ] = true; | |
194 } | |
195 | |
196 } | |
197 | |
198 bool[ DBusObjectImpl ] objectLocker; | |
199 | |
200 | |
201 class DBusConnectionImpl { | |
202 DBusConnection* conn; | |
203 | |
204 public this( char[] addr ){ | |
205 DBusError err; | |
206 int trial = 0; | |
207 while( true ){ | |
208 trial++; | |
209 dbus_error_init(&err); | |
210 | |
211 scope(exit) | |
212 if( dbus_error_is_set(&err) ){ | |
213 dbus_error_free(&err); | |
214 } | |
215 | |
216 conn = dbus_connection_open_private( XtoUtf8z(addr), & err ); | |
217 | |
218 if( !dbus_error_is_set(&err) && conn !is null ){ | |
219 return; | |
220 } | |
221 if( trial > 10 ){ | |
222 if( dbus_error_is_set(&err) ){ | |
223 Stdout.formatln( "Connect Error ({})\n", fromUtf8z( err.message)); | |
224 throw new Exception(""); | |
225 } | |
226 if( conn is null ){ | |
227 throw new IOException("connecting not successful"); | |
228 } | |
229 } | |
230 else{ | |
231 Thread.sleep( 0.1 ); | |
232 } | |
233 } | |
234 } | |
235 | |
236 /+ public DBusInterface getRemoteObject( char[] path ){ | |
237 return null; | |
238 }+/ | |
239 public void mainLoop(){ | |
240 //Stdout.formatln( " D mainloop starting" ); | |
241 while (dbus_connection_read_write_dispatch (conn, -1)){ | |
242 //Stdout.formatln( " D mainloop" ); | |
243 // empty loop body | |
244 } | |
245 //Stdout.formatln( " D mainloop stop" ); | |
246 return; | |
247 | |
248 DBusError err; | |
249 dbus_error_init(&err); | |
250 //CBus.dbus_bus_request_name(conn, XtoUtf8z("test.method.caller"), DBUS_NAME_FLAG_REPLACE_EXISTING , &err); | |
251 if( dbus_error_is_set(&err) ){ | |
252 Stdout.formatln( "Name Error ({})\n", fromUtf8z( err.message)); | |
253 dbus_error_free(&err); | |
254 throw new Exception(""); | |
255 } | |
256 } | |
257 public void disconnect(){ | |
258 if( conn !is null ){ | |
259 dbus_connection_close( conn ); | |
260 } | |
261 } | |
262 } | |
263 | |
264 class DirectConnection : DBusConnectionImpl { | |
265 public this( char[] addr ){ | |
266 super( addr ); | |
267 } | |
268 } | |
269 | |
270 | |
271 | |
272 class DBusExecutionException : TracedException { | |
273 public this( char[] msg ){ | |
274 super( msg ); | |
275 } | |
276 } | |
277 | |
278 template isDBusSimpleType(T){ | |
279 const bool isDBusSimpleType = | |
280 is( T == bool ) || | |
281 is( T == byte ) || | |
282 is( T == short ) || | |
283 is( T == ushort ) || | |
284 is( T == int ) || | |
285 is( T == uint ) || | |
286 is( T == long ) || | |
287 is( T == ulong ) || | |
288 is( T == double ); | |
289 } | |
290 | |
291 | |
292 private void getCallValue( T )( DBusMessageIter* iter, out T t ){ | |
293 version(CD) pragma( msg, "getCallValue: "~T.stringof ); | |
294 | |
295 void testType( int type ){ | |
296 int expected = dbus_message_iter_get_arg_type( iter ); | |
297 ensure( expected == type, "getCallType(%0) type does not match %1 '%2' != %3 '%4'", T.stringof, toUtf8(type), [cast(char)type], toUtf8(expected), [cast(char)expected] ); | |
298 } | |
299 | |
300 static if( false ){} | |
301 else static if( isAssocArrayType!(T) ){ | |
302 version(CD) pragma( msg, "getCallValue: assic "~typeof(T).stringof ); | |
303 testType( DBUS_TYPE_ARRAY ); | |
304 DBusMessageIter sub; | |
305 dbus_message_iter_recurse( iter, &sub ); | |
306 dbus_message_iter_next( iter ); | |
307 | |
308 typeof(T.keys [0]) key; | |
309 typeof(T.values[0]) value; | |
310 while( dbus_message_iter_get_arg_type( &sub ) != DBUS_TYPE_INVALID ){ | |
311 ensure( dbus_message_iter_get_arg_type( &sub ) == DBUS_TYPE_DICT_ENTRY, "getCallType type does not match for Assoc" ); | |
312 DBusMessageIter entry; | |
313 dbus_message_iter_recurse( &sub, &entry ); | |
314 dbus_message_iter_next( &sub ); | |
315 | |
316 getCallValue( &entry, key ); | |
317 getCallValue( &entry, value ); | |
318 t[ key ] = value; | |
319 } | |
320 } | |
321 else static if( is( T == char[] )){ // char[] nicht als dyn array, sondern als String | |
322 testType( DBUS_TYPE_STRING ); | |
323 char* ptr; | |
324 dbus_message_iter_get_basic( iter, & ptr ); | |
325 dbus_message_iter_next( iter ); | |
326 t = fromUtf8z( ptr ); | |
327 } | |
328 else static if( isDynamicArrayType!(T) ){ | |
329 testType( DBUS_TYPE_ARRAY ); | |
330 DBusMessageIter sub; | |
331 dbus_message_iter_recurse( iter, &sub ); | |
332 dbus_message_iter_next( iter ); | |
333 static if( is( typeof(T[0]) == bool )) { | |
334 version(CD) pragma( msg, "getCallValue: basic type "~typeof(T[0]).stringof ); | |
335 if( dbus_message_iter_get_arg_type( &sub ) != DBUS_TYPE_INVALID ){ | |
336 // special processing because of dbus bools are 4bytes vs. D bool is 1byte. | |
337 dbus_bool_t* ptr; | |
338 int n_elements; | |
339 dbus_message_iter_get_fixed_array( & sub, &ptr, & n_elements ); | |
340 t.length = n_elements; | |
341 foreach( idx, v; ptr[ 0 .. n_elements ] ){ | |
342 t[ idx ] = ( v != 0 ); | |
343 } | |
344 } | |
345 } | |
346 else static if( isDBusSimpleType!( typeof(T[0]) )) { | |
347 version(CD) pragma( msg, "getCallValue: basic type "~typeof(T[0]).stringof ); | |
348 if( dbus_message_iter_get_arg_type( &sub ) != DBUS_TYPE_INVALID ){ | |
349 typeof(T[0])* ptr; | |
350 int n_elements; | |
351 dbus_message_iter_get_fixed_array( & sub, &ptr, & n_elements ); | |
352 t = ptr[ 0 .. n_elements ].dup; | |
353 } | |
354 } | |
355 else{ | |
356 version(CD) pragma( msg, "getCallValue: composed type "~typeof(T[0]).stringof ); | |
357 uint idx = 0; | |
358 while( dbus_message_iter_get_arg_type( &sub ) != DBUS_TYPE_INVALID ){ | |
359 t.length = t.length +1; | |
360 getCallValue( &sub, t[idx] ); | |
361 // dbus_message_iter_next( &sub ) : is done in getCallValue for element. | |
362 idx++; | |
363 } | |
364 } | |
365 } | |
366 else static if( isDBusSimpleType!(T) ) { | |
367 testType( DBusTypeIdFromDType!(T) ); | |
368 dbus_message_iter_get_basic( iter, & t ); | |
369 dbus_message_iter_next( iter ); | |
370 } | |
371 else static if( is( T : DBusObjectImpl )){ | |
372 testType( DBusTypeIdFromDType!(T) ); | |
373 static assert( false ); | |
374 } | |
375 else static if( is( T == DBusVariant ) ){ | |
376 DBusMessageIter sub; | |
377 dbus_message_iter_recurse( iter, &sub ); | |
378 dbus_message_iter_next( iter ); | |
379 char* sig = dbus_message_iter_get_signature( &sub ); | |
380 scope(exit) dbus_free( sig ); | |
381 char[] sigText = fromUtf8z( sig ); | |
382 t = createDBusVariant( &sub, sigText ); | |
383 } | |
384 else static if( is( T == Struct!(typeof(T.t)) ) ){ | |
385 // Stdout.formatln( "DBus getCallValue {}", __LINE__ ); | |
386 DBusMessageIter sub; | |
387 dbus_message_iter_recurse( iter, &sub ); | |
388 dbus_message_iter_next( iter ); | |
389 foreach( idx, el; t.t ){ | |
390 getCallValue( & sub, t.t[idx] ); | |
391 } | |
392 } | |
393 else{ | |
394 pragma( msg, "getCallValue: "~typeof(t).stringof ); | |
395 static assert(false, typeof(t).stringof ); | |
396 } | |
397 } | |
398 | |
399 public Struct!(T) getCallValues( T... )( DBusMessage* message ){ | |
400 version(CD) pragma( msg, "getCallValues: "~T.stringof ); | |
401 Struct!(T) res; | |
402 DBusMessageIter args; | |
403 dbus_message_iter_init( message, &args); | |
404 foreach( idx, t; T ){ | |
405 getCallValue( &args, res.t[idx] ); | |
406 } | |
407 return res; | |
408 } | |
409 | |
410 | |
411 private void _appendMsgParam( DBusMessageIter* iter, int type, void* ptr ){ | |
412 if ( !dbus_message_iter_append_basic( iter, type, ptr ) ) { | |
413 throw new TracedException( "Cannot append argument to iterator" ); | |
414 } | |
415 } | |
416 | |
417 | |
418 void appendMsgParam( DBusConnection* conn, DBusMessageIter* iter, bool value ){ | |
419 dbus_bool_t val = value; | |
420 _appendMsgParam( iter, DBUS_TYPE_BOOLEAN, &val ); | |
421 } | |
422 void appendMsgParam( DBusConnection* conn, DBusMessageIter* iter, byte value ){ | |
423 dbus_bool_t val = value; | |
424 _appendMsgParam( iter, DBUS_TYPE_BYTE, &val ); | |
425 } | |
426 void appendMsgParam( DBusConnection* conn, DBusMessageIter* iter, short value ){ | |
427 dbus_int16_t val = value; | |
428 _appendMsgParam( iter, DBUS_TYPE_INT16, &val ); | |
429 } | |
430 void appendMsgParam( DBusConnection* conn, DBusMessageIter* iter, ushort value ){ | |
431 dbus_uint16_t val = value; | |
432 _appendMsgParam( iter, DBUS_TYPE_UINT16, &val ); | |
433 } | |
434 void appendMsgParam( DBusConnection* conn, DBusMessageIter* iter, int value ){ | |
435 dbus_int32_t val = value; | |
436 _appendMsgParam( iter, DBUS_TYPE_INT32, &val ); | |
437 } | |
438 void appendMsgParam( DBusConnection* conn, DBusMessageIter* iter, uint value ){ | |
439 dbus_int32_t val = value; | |
440 _appendMsgParam( iter, DBUS_TYPE_UINT32, &val ); | |
441 } | |
442 void appendMsgParam( DBusConnection* conn, DBusMessageIter* iter, long value ){ | |
443 dbus_int64_t val = value; | |
444 _appendMsgParam( iter, DBUS_TYPE_INT64, &val ); | |
445 } | |
446 void appendMsgParam( DBusConnection* conn, DBusMessageIter* iter, ulong value ){ | |
447 dbus_uint64_t val = value; | |
448 _appendMsgParam( iter, DBUS_TYPE_UINT64, &val ); | |
449 } | |
450 void appendMsgParam( DBusConnection* conn, DBusMessageIter* iter, double value ){ | |
451 double val = value; | |
452 _appendMsgParam( iter, DBUS_TYPE_DOUBLE, &val ); | |
453 } | |
454 | |
455 | |
456 | |
457 private const char[] nullChar = "\0"; | |
458 char* XtoUtf8z (char[] s) { | |
459 if (s.length == 0) | |
460 return nullChar.ptr; | |
461 if (s[$-1] == '\0') | |
462 return s.ptr; | |
463 s ~= '\0'; | |
464 return s.ptr; | |
465 } | |
466 | |
467 void appendMsgParam( DBusConnection* conn, DBusMessageIter* iter, char[] value ){ | |
468 //toUtf8z( value ); // toUtf8z return null for a null char[], but a valid ptr is needed. | |
469 char* val = XtoUtf8z( value ); | |
470 _appendMsgParam( iter, DBUS_TYPE_STRING, &val ); | |
471 } | |
472 | |
473 void appendMsgParamObject( DBusConnection* conn, DBusMessageIter* iter, DBusObjectImpl value ){ | |
474 value.registerDBusObject( conn ); | |
475 char* path = XtoUtf8z( value.getDBusInstanceName()); | |
476 _appendMsgParam( iter, DBUS_TYPE_OBJECT_PATH, &path ); | |
477 } | |
478 | |
479 void appendMsgParamVariant( DBusConnection* conn, DBusMessageIter* iter, DBusVariant value ){ | |
480 DBusMessageIter sub; | |
481 ensureDBus( dbus_message_iter_open_container( iter, DBUS_TYPE_VARIANT, XtoUtf8z( value.getSig() ), &sub )); | |
482 if( DBusVariantValueBool v = cast(DBusVariantValueBool)value ){ | |
483 appendMsgParam( conn, &sub, v.value ); | |
484 } | |
485 else if( DBusVariantValueByte v = cast(DBusVariantValueByte)value ){ | |
486 appendMsgParam( conn, &sub, v.value ); | |
487 } | |
488 else if( DBusVariantValueShort v = cast(DBusVariantValueShort)value ){ | |
489 appendMsgParam( conn, &sub, v.value ); | |
490 } | |
491 else if( DBusVariantValueUShort v = cast(DBusVariantValueUShort)value ){ | |
492 appendMsgParam( conn, &sub, v.value ); | |
493 } | |
494 else if( DBusVariantValueInt v = cast(DBusVariantValueInt)value ){ | |
495 appendMsgParam( conn, &sub, v.value ); | |
496 } | |
497 else if( DBusVariantValueUInt v = cast(DBusVariantValueUInt)value ){ | |
498 appendMsgParam( conn, &sub, v.value ); | |
499 } | |
500 else if( DBusVariantValueLong v = cast(DBusVariantValueLong)value ){ | |
501 appendMsgParam( conn, &sub, v.value ); | |
502 } | |
503 else if( DBusVariantValueULong v = cast(DBusVariantValueULong)value ){ | |
504 appendMsgParam( conn, &sub, v.value ); | |
505 } | |
506 else if( DBusVariantValueDouble v = cast(DBusVariantValueDouble)value ){ | |
507 appendMsgParam( conn, &sub, v.value ); | |
508 } | |
509 else if( DBusVariantValueString v = cast(DBusVariantValueString)value ){ | |
510 appendMsgParam( conn, &sub, v.value ); | |
511 } | |
512 | |
513 else if( DBusVariantStruct v = cast(DBusVariantStruct)value ){ | |
514 DBusMessageIter sub2; | |
515 ensureDBus( dbus_message_iter_open_container( &sub, DBUS_TYPE_STRUCT, XtoUtf8z( v.getSig() ), &sub2 )); | |
516 foreach( el; v.values ){ | |
517 appendMsgParamVariant( conn, &sub2, el ); | |
518 } | |
519 ensureDBus( dbus_message_iter_close_container( &sub, &sub2 )); | |
520 } | |
521 else if( DBusVariantArray v = cast(DBusVariantArray)value ){ | |
522 DBusMessageIter sub2; | |
523 ensureDBus( dbus_message_iter_open_container( &sub, DBUS_TYPE_ARRAY, XtoUtf8z( v.getSig() ), &sub2 )); | |
524 foreach( el; v.values ){ | |
525 appendMsgParamVariant( conn, &sub2, el ); | |
526 } | |
527 ensureDBus( dbus_message_iter_close_container( &sub, &sub2 )); | |
528 } | |
529 else if( DBusVariantMap v = cast(DBusVariantMap)value ){ | |
530 DBusMessageIter sub2; | |
531 ensureDBus( dbus_message_iter_open_container( &sub, DBUS_TYPE_ARRAY, XtoUtf8z( v.getSig() ), &sub2 )); | |
532 foreach( entry; v.values ){ | |
533 DBusMessageIter el; | |
534 ensureDBus( dbus_message_iter_open_container( &sub2, DBUS_TYPE_DICT_ENTRY, null, &el )); | |
535 appendMsgParamVariant( conn, &el, entry.key ); | |
536 appendMsgParamVariant( conn, &el, entry.value ); | |
537 ensureDBus( dbus_message_iter_close_container( &sub2, &el )); | |
538 } | |
539 ensureDBus( dbus_message_iter_close_container( &sub, &sub2 )); | |
540 } | |
541 else{ | |
542 Stdout.formatln( "appendMsgParamVariant not handled case for sig: {}", value.getSig() ).flush(); | |
543 ensure( false, "appendMsgParamVariant not handled case for sig: %0", value.getSig() ); | |
544 } | |
545 ensureDBus( dbus_message_iter_close_container( iter, &sub )); | |
546 } | |
547 | |
548 void appendMsgParamArray( T )( DBusConnection* conn, DBusMessageIter* iter, T[] value ){ | |
549 //pragma( msg, "appendMsgParamArray: "~typeof(T).stringof ); | |
550 DBusMessageIter sub; | |
551 //Stderr.formatln( "DBus {} {}", __LINE__,createDBusSignature!(T) ).flush; | |
552 ensureDBus( dbus_message_iter_open_container( iter, DBUS_TYPE_ARRAY, XtoUtf8z( createDBusSignature!(T)), &sub )); | |
553 foreach( item; value ){ | |
554 appendItem!( typeof( item ))( conn, &sub, item ); | |
555 } | |
556 ensureDBus( dbus_message_iter_close_container( iter, &sub )); | |
557 } | |
558 | |
559 void appendMsgParamStruct( T... )( DBusConnection* conn, DBusMessageIter* iter, T t ){ | |
560 //pragma( msg, "appendMsgParamStruct: "~typeof(T).stringof ); | |
561 DBusMessageIter sub; | |
562 ensureDBus( dbus_message_iter_open_container( iter, DBUS_TYPE_STRUCT, XtoUtf8z( createDBusSignature!(T)), &sub )); | |
563 foreach( item; t ){ | |
564 appendItem( conn, &sub, item ); | |
565 } | |
566 ensureDBus( dbus_message_iter_close_container( iter, &sub )); | |
567 } | |
568 | |
569 void appendMsgParamAssoc( K, V )( DBusConnection* conn, DBusMessageIter* iter, V[K] map ){ | |
570 //pragma( msg, "appendMsgParamAssoc: key="~typeof(K).stringof~" value="~typeof(V).stringof ); | |
571 DBusMessageIter sub; | |
572 ensureDBus( dbus_message_iter_open_container( iter, DBUS_TYPE_ARRAY, | |
573 XtoUtf8z( createDBusSignature!(V[K])[1..$] ), // "{ss}" this is without the leading 'a' for the array. | |
574 &sub )); | |
575 foreach( key, value; map ){ | |
576 DBusMessageIter el; | |
577 ensureDBus( dbus_message_iter_open_container( &sub, DBUS_TYPE_DICT_ENTRY, null, &el )); | |
578 appendItem!( K )( conn, &el, key ); | |
579 appendItem!( V )( conn, &el, value ); | |
580 ensureDBus( dbus_message_iter_close_container( &sub, &el )); | |
581 } | |
582 ensureDBus( dbus_message_iter_close_container( iter, &sub )); | |
583 } | |
584 | |
585 template createDBusSignature(T...){ | |
586 //pragma( msg, "createDBusSignature(T) : T="~typeof(T).stringof ); | |
587 static if( T.length > 1 ){ | |
588 //pragma( msg, "R.length>1" ); | |
589 const char[] createDBusSignature = createDBusSignature!(T[0]) ~ createDBusSignature!(T[1..$]); | |
590 } | |
591 else static if( isAssocArrayType!(T[0]) ){ | |
592 //pragma( msg, "createDBusSignature: key="~typeof(T.keys[0] ).stringof~" value="~typeof(T.values[0] ).stringof ); | |
593 const char[] createDBusSignature = | |
594 DBUS_TYPE_ARRAY_AS_STRING ~ | |
595 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING ~ | |
596 createDBusSignature!( typeof(T[0].keys[0] )) ~ | |
597 createDBusSignature!( typeof(T[0].values[0] )) ~ | |
598 DBUS_DICT_ENTRY_END_CHAR_AS_STRING; | |
599 } | |
600 else static if( isDynamicArrayType!(T[0]) ){ | |
601 //pragma( msg, "createDBusSignature: arr="~typeof(T[0]).stringof ); | |
602 static if( is( T[0] == char[] ) ){ | |
603 const char[] createDBusSignature = DBUS_TYPE_STRING_AS_STRING; | |
604 } | |
605 else{ | |
606 const char[] createDBusSignature = DBUS_TYPE_ARRAY_AS_STRING ~ createDBusSignature!(typeof(T[0][0])); | |
607 } | |
608 } | |
609 else static if( is( T[0] == bool ) ){ const char[] createDBusSignature = DBUS_TYPE_BOOLEAN_AS_STRING; } | |
610 else static if( is( T[0] == byte ) ){ const char[] createDBusSignature = DBUS_TYPE_BYTE_AS_STRING; } | |
611 else static if( is( T[0] == short ) ){ const char[] createDBusSignature = DBUS_TYPE_INT16_AS_STRING; } | |
612 else static if( is( T[0] == ushort ) ){ const char[] createDBusSignature = DBUS_TYPE_UINT16_AS_STRING; } | |
613 else static if( is( T[0] == int ) ){ const char[] createDBusSignature = DBUS_TYPE_INT32_AS_STRING; } | |
614 else static if( is( T[0] == uint ) ){ const char[] createDBusSignature = DBUS_TYPE_UINT32_AS_STRING; } | |
615 else static if( is( T[0] == long ) ){ const char[] createDBusSignature = DBUS_TYPE_INT64_AS_STRING; } | |
616 else static if( is( T[0] == ulong ) ){ const char[] createDBusSignature = DBUS_TYPE_UINT64_AS_STRING; } | |
617 else static if( is( T[0] == double ) ){ const char[] createDBusSignature = DBUS_TYPE_DOUBLE_AS_STRING; } | |
618 else static if( is( T[0] : DBusObjectImpl ) ){ const char[] createDBusSignature = DBUS_TYPE_OBJECT_PATH_AS_STRING; } | |
619 else static if( is( T[0] == DBusVariant ) ){ const char[] createDBusSignature = DBUS_TYPE_VARIANT_AS_STRING; } | |
620 else static if( is( T[0] == Struct!(typeof(T[0].t)) )){ | |
621 //pragma( msg, "createDBusSignature Struct: t="~typeof(T[0].t).stringof ); | |
622 const char[] createDBusSignature = | |
623 DBUS_STRUCT_BEGIN_CHAR_AS_STRING ~ | |
624 createDBusSignature!( typeof(T[0].t) ) ~ | |
625 DBUS_STRUCT_END_CHAR_AS_STRING; | |
626 } | |
627 else { | |
628 pragma( msg, "createDBusSignature(T) : T="~typeof(T).stringof ); | |
629 static assert( false ); | |
630 } | |
631 } | |
632 | |
633 template DBusTypeIdFromDType(T){ | |
634 //pragma( msg, "DBusTypeIdFromDType: "~typeof(T).stringof ); | |
635 static if(false){} | |
636 else static if( is( T == char[] ) ){ const int DBusTypeIdFromDType = DBUS_TYPE_STRING; } | |
637 else static if( isDynamicArrayType!(T) ){ const int DBusTypeIdFromDType = DBUS_TYPE_ARRAY; } | |
638 else static if( is( T == bool ) ){ const int DBusTypeIdFromDType = DBUS_TYPE_BOOLEAN; } | |
639 else static if( is( T == byte ) ){ const int DBusTypeIdFromDType = DBUS_TYPE_BYTE; } | |
640 else static if( is( T == short ) ){ const int DBusTypeIdFromDType = DBUS_TYPE_INT16; } | |
641 else static if( is( T == ushort ) ){ const int DBusTypeIdFromDType = DBUS_TYPE_UINT16; } | |
642 else static if( is( T == int ) ){ const int DBusTypeIdFromDType = DBUS_TYPE_INT32; } | |
643 else static if( is( T == uint ) ){ const int DBusTypeIdFromDType = DBUS_TYPE_UINT32; } | |
644 else static if( is( T == long ) ){ const int DBusTypeIdFromDType = DBUS_TYPE_INT64; } | |
645 else static if( is( T == ulong ) ){ const int DBusTypeIdFromDType = DBUS_TYPE_UINT64; } | |
646 else static if( is( T == double ) ){ const int DBusTypeIdFromDType = DBUS_TYPE_DOUBLE; } | |
647 else static if( is( T : DBusObjectImpl ) ){ const int DBusTypeIdFromDType = DBUS_TYPE_OBJECT_PATH; } | |
648 else static if( is( T == DBusVariant ) ){ const int DBusTypeIdFromDType = DBUS_TYPE_OBJECT_PATH; } | |
649 else static if( is( T == Struct!(typeof(T.t)) ) ){ const int DBusTypeIdFromDType = DBUS_TYPE_OBJECT_PATH; } | |
650 else static assert(false); | |
651 } | |
652 | |
653 void appendItem( T... )( DBusConnection* conn, DBusMessageIter * args, T t ){ | |
654 //pragma( msg, ">>>appendItem input: "~typeof(t).stringof ); | |
655 //Stderr.formatln( "DBus {} {}", __LINE__,T[0].stringof ).flush; | |
656 static if( T.length > 1 ){ | |
657 //pragma( msg, "T.length>1" ); | |
658 appendItem(T[0])( conn, args, t[0] ); | |
659 appendItem(T[1..$])( conn, args, t[1..$] ); | |
660 } | |
661 else static if( isAssocArrayType!(T[0]) ){ | |
662 //pragma( msg, ">>> appendItem: assoc" ); | |
663 //Stdout.formatln( "DBus {}", __LINE__ ); | |
664 appendMsgParamAssoc( conn, args, t[0] ); | |
665 } | |
666 else static if( is( T[0] == char[] )){ // char[] nicht als dyn array, sondern als String | |
667 //pragma( msg, ">>> appendItem: char[]" ); | |
668 appendMsgParam( conn, args, t[0]); | |
669 } | |
670 else static if( isDynamicArrayType!(T[0]) ){ | |
671 //pragma( msg, ">>> appendItem: []" ); | |
672 //Stdout.formatln( "DBus {}", __LINE__ ); | |
673 appendMsgParamArray( conn, args, t[0] ); | |
674 } | |
675 else static if( isDBusSimpleType!( T[0] ) ) { | |
676 //pragma( msg, ">>> appendItem: integral" ); | |
677 appendMsgParam( conn, args, t[0] ); | |
678 } | |
679 else static if( is( T[0] : DBusObjectImpl )){ | |
680 //pragma( msg, ">>> appendItem: interface/class" ); | |
681 appendMsgParamObject( conn, args, cast(DBusObjectImpl)t[0]); | |
682 } | |
683 else static if( is( T[0] == DBusVariant ) ){ | |
684 appendMsgParamVariant( conn, args, t[0]); | |
685 } | |
686 else static if( is( T[0] == DBusObjPath ) ){ | |
687 //pragma( msg, ">>> appendItem: path" ); | |
688 Stdout.formatln( "DBus {}", __LINE__ ); | |
689 notImplemented(); | |
690 } | |
691 else static if( is( T[0] == DBusSignature ) ){ | |
692 //pragma( msg, ">>> appendItem: sig" ); | |
693 Stdout.formatln( "DBus {}", __LINE__ ); | |
694 notImplemented(); | |
695 } | |
696 else static if( is( T[0] == Struct!(typeof(T[0].t)) ) ){ | |
697 //pragma( msg, ">>> appendItem: struct" ); | |
698 appendMsgParamStruct( conn, args, t[0].t ); | |
699 //pragma( msg, "struct: "~typeof(t).stringof ); | |
700 } | |
701 else{ | |
702 pragma( msg, "appendItem: "~typeof(t).stringof ); | |
703 static assert(false, typeof(t).stringof ); | |
704 } | |
705 } | |
706 | |
707 void sendReply( DBusConnection* conn, DBusMessage* message ){ | |
708 | |
709 Stdout.flush(); | |
710 Stderr.flush(); | |
711 | |
712 DBusMessage* reply = dbus_message_new_method_return(message); | |
713 scope(exit){ | |
714 dbus_message_unref(reply); | |
715 } | |
716 dbus_bool_t res = dbus_connection_send(conn, reply, null ); | |
717 dbus_connection_flush(conn); | |
718 if( !res ){ | |
719 throw new TracedException( "Cannot send. Out of memory." ); | |
720 } | |
721 } | |
722 | |
723 void sendReplyData( T... )( DBusConnection* conn, DBusMessage* message, Struct!(T) t ){ | |
724 | |
725 Stdout.flush(); | |
726 Stderr.flush(); | |
727 | |
728 //Stdout.formatln( "DBus {}", __LINE__ ); | |
729 DBusMessage* reply = dbus_message_new_method_return(message); | |
730 scope(exit){ | |
731 dbus_message_unref(reply); | |
732 } | |
733 //Stdout.formatln( "DBus {}", __LINE__ ); | |
734 | |
735 static if( t.t.length > 0 ){ | |
736 DBusMessageIter args; | |
737 dbus_message_iter_init_append( reply, &args); | |
738 foreach( t_item; t.t ){ | |
739 //Stdout.formatln( "DBus {}", __LINE__ ); | |
740 //pragma( msg, "sendReply t: "~typeof(t).stringof ); | |
741 //pragma( msg, "sendReply t_item: "~typeof(t_item).stringof ); | |
742 appendItem( conn, & args, t_item ); | |
743 //pragma( msg, "sendReply OK" ); | |
744 } | |
745 } | |
746 //Stdout.formatln( "DBus {}", __LINE__ ); | |
747 //Stdout.formatln( "reply sig : {}", fromUtf8z(dbus_message_get_signature(reply))); | |
748 dbus_bool_t res = dbus_connection_send(conn, reply, null ); | |
749 dbus_connection_flush(conn); | |
750 if( !res ){ | |
751 throw new TracedException( "Cannot send. Out of memory." ); | |
752 } | |
753 } | |
754 | |
755 void sendException( DBusConnection* conn, DBusMessage* message, Exception e ){ | |
756 | |
757 Stdout.flush(); | |
758 Stderr.flush(); | |
759 | |
760 char* type; | |
761 char[] msg = e.msg; | |
762 if( IOException e2 = cast(IOException)e ){ | |
763 type = XtoUtf8z(DBUS_ERROR_IO_ERROR); | |
764 msg = "IOException " ~ msg; | |
765 } | |
766 else{ | |
767 type = XtoUtf8z(DBUS_ERROR_FAILED); | |
768 } | |
769 if( TracedException te = cast(TracedException)e ){ | |
770 foreach( m; te ){ | |
771 msg ~= m ~ \n; | |
772 } | |
773 } | |
774 | |
775 DBusMessage* reply = | |
776 dbus_message_new_error(message, type, XtoUtf8z("D Exception: " ~ msg) ); | |
777 scope(exit){ | |
778 dbus_message_unref(reply); | |
779 } | |
780 dbus_bool_t res = dbus_connection_send(conn, reply, null ); | |
781 dbus_connection_flush(conn); | |
782 if( !res ){ | |
783 throw new TracedException( "Cannot send. Out of dbus-memory." ); | |
784 } | |
785 } | |
786 | |
787 bool checkIntf( char[] intfName, DBusMessage* message ){ | |
788 char[] namedInterface = fromUtf8z( dbus_message_get_interface(message)); | |
789 if( namedInterface.length == 0 ){ | |
790 return true; // no interface named in call, so lets try | |
791 } | |
792 return namedInterface == intfName; | |
793 } | |
794 | |
795 public const int METHOD_SIG_MAXLENGTH = 100; | |
796 | |
797 char[] methodSignature( DBusMessage* message, char[] buf = null ){ | |
798 char[] name = fromUtf8z( dbus_message_get_member(message)); | |
799 if( buf.length < name.length ){ | |
800 buf.length = name.length; | |
801 } | |
802 buf[ 0 .. name.length ] = name; | |
803 | |
804 char[] sig = fromUtf8z( dbus_message_get_signature(message)); | |
805 int sz = name.length+sig.length+1; | |
806 if( buf.length < sz ){ | |
807 buf.length= sz; | |
808 } | |
809 int type = dbus_message_get_type( message ); | |
810 switch( type ){ | |
811 case DBUS_MESSAGE_TYPE_METHOD_CALL: | |
812 buf[name.length] = '|'; | |
813 break; | |
814 case DBUS_MESSAGE_TYPE_SIGNAL: | |
815 buf[name.length] = '>'; | |
816 break; | |
817 case DBUS_MESSAGE_TYPE_METHOD_RETURN: | |
818 case DBUS_MESSAGE_TYPE_ERROR: | |
819 case DBUS_MESSAGE_TYPE_INVALID: | |
820 default: | |
821 ensure( false, "methodSignature for unknown type %0", toUtf8(type) ); | |
822 } | |
823 buf[name.length+1 .. sz ] = sig; | |
824 return buf[0..sz]; | |
825 } | |
826 | |
827 char[] nextSingleCompleteTypeSig( char[] sigText, inout int ate = 0 ){ | |
828 if( sigText.length > ate || sigText.length == 0 ){ | |
829 return null; | |
830 } | |
831 char[] sig = sigText[ ate .. $ ]; | |
832 | |
833 switch( sig[0] ){ | |
834 case 'y': | |
835 case 'b': | |
836 case 'n': | |
837 case 'q': | |
838 case 'i': | |
839 case 'u': | |
840 case 'x': | |
841 case 't': | |
842 case 'd': | |
843 case 's': | |
844 case 'o': | |
845 case 'g': | |
846 case 'v': | |
847 ate = 1; | |
848 return sig[0..1]; | |
849 default: | |
850 ensure( sig.length > 1, "nextSingleCompleteTypeSig found %0 as a single type sig, which is unknown", sig[0..1] ); | |
851 } | |
852 | |
853 if( sig[0] == 'a' ){ | |
854 if( sig[ 1 ] == '{' ){ | |
855 int idx = 2; | |
856 nextSingleCompleteTypeSig( sig, idx ); | |
857 nextSingleCompleteTypeSig( sig, idx ); | |
858 ensure( sig.length > idx, "nextSingleCompleteTypeSig 2" ); | |
859 ensure( sig[ idx ] == '}', "nextSingleCompleteTypeSig 3" ); | |
860 idx++; | |
861 ate += idx; | |
862 return sig[ 0 .. idx ]; | |
863 } | |
864 else{ | |
865 int idx = 1; | |
866 nextSingleCompleteTypeSig( sig, idx ); | |
867 ate += idx; | |
868 return sig[ 0 .. idx ]; | |
869 } | |
870 } | |
871 else if( sig[0] == '(' ){ | |
872 int idx = 1; | |
873 ensure( sig.length > idx, "nextSingleCompleteTypeSig 4" ); | |
874 while( sig[ idx ] != ')' ){ | |
875 nextSingleCompleteTypeSig( sig, idx ); | |
876 ensure( sig.length > idx, "nextSingleCompleteTypeSig 5" ); | |
877 } | |
878 idx++; | |
879 ate += idx; | |
880 return sig[ 0 .. idx ]; | |
881 } | |
882 assert(false); | |
883 } | |
884 | |
885 DBusVariant createDBusVariant( DBusMessageIter * iter, char[] sigText ){ | |
886 if( sigText.length == 0 ){ | |
887 return null; | |
888 } | |
889 | |
890 void getBasic( void* ptr ){ | |
891 dbus_message_iter_get_basic( iter, ptr ); | |
892 dbus_message_iter_next( iter ); | |
893 } | |
894 | |
895 switch( sigText[0] ){ | |
896 case 'y': | |
897 { | |
898 DBusVariantValueByte res = new DBusVariantValueByte(); | |
899 getBasic( & res.value ); | |
900 return res; | |
901 } | |
902 case 'b': | |
903 { | |
904 DBusVariantValueBool res = new DBusVariantValueBool(); | |
905 getBasic( & res.value ); | |
906 return res; | |
907 } | |
908 case 'n': | |
909 { | |
910 DBusVariantValueShort res = new DBusVariantValueShort(); | |
911 getBasic( & res.value ); | |
912 return res; | |
913 } | |
914 case 'q': | |
915 { | |
916 DBusVariantValueUShort res = new DBusVariantValueUShort(); | |
917 getBasic( & res.value ); | |
918 return res; | |
919 } | |
920 case 'i': | |
921 { | |
922 DBusVariantValueInt res = new DBusVariantValueInt(); | |
923 getBasic( & res.value ); | |
924 return res; | |
925 } | |
926 case 'u': | |
927 { | |
928 DBusVariantValueUInt res = new DBusVariantValueUInt(); | |
929 getBasic( & res.value ); | |
930 return res; | |
931 } | |
932 case 'x': | |
933 { | |
934 DBusVariantValueLong res = new DBusVariantValueLong(); | |
935 getBasic( & res.value ); | |
936 return res; | |
937 } | |
938 case 't': | |
939 { | |
940 DBusVariantValueULong res = new DBusVariantValueULong(); | |
941 getBasic( & res.value ); | |
942 return res; | |
943 } | |
944 case 'd': | |
945 { | |
946 DBusVariantValueDouble res = new DBusVariantValueDouble(); | |
947 getBasic( & res.value ); | |
948 return res; | |
949 } | |
950 case 's': | |
951 { | |
952 DBusVariantValueString res = new DBusVariantValueString(); | |
953 char* ptr; | |
954 getBasic( & ptr ); | |
955 res.value = fromUtf8z( ptr ); | |
956 return res; | |
957 } | |
958 case 'v': | |
959 { | |
960 DBusVariantValueVariant res = new DBusVariantValueVariant(); | |
961 DBusMessageIter subIter; | |
962 dbus_message_iter_recurse( iter, &subIter ); | |
963 dbus_message_iter_next( iter ); | |
964 res.value = createDBusVariant( & subIter, sigText[1..$] ); | |
965 return res; | |
966 } | |
967 case 'o': //"DBusObject" | |
968 assert(false); | |
969 case 'g': //"DBusSignature" | |
970 assert(false); | |
971 default: | |
972 break; | |
973 } | |
974 if( sigText[0] == 'a' ){ | |
975 if( sigText.length > 1 && sigText[ 1 ] == '{' ){ | |
976 int idx = 2; | |
977 char[] sigKey = nextSingleCompleteTypeSig( sigText, idx ); | |
978 char[] sigValue = nextSingleCompleteTypeSig( sigText, idx ); | |
979 DBusVariantMap res = new DBusVariantMap( sigKey, sigValue ); | |
980 | |
981 DBusMessageIter subIter; | |
982 dbus_message_iter_recurse( iter, &subIter ); | |
983 dbus_message_iter_next( iter ); | |
984 | |
985 while( dbus_message_iter_get_arg_type( &subIter ) != DBUS_TYPE_INVALID ){ | |
986 ensure( dbus_message_iter_get_arg_type( &subIter ) == DBUS_TYPE_DICT_ENTRY, "createDBusVariant 1" ); | |
987 DBusMessageIter entry; | |
988 dbus_message_iter_recurse( &subIter, &entry ); | |
989 dbus_message_iter_next( &subIter ); | |
990 | |
991 DBusVariantMapItem item; | |
992 item.key = createDBusVariant( & subIter, sigKey ); | |
993 item.value = createDBusVariant( & subIter, sigValue ); | |
994 res.values ~= item; | |
995 } | |
996 return res; | |
997 } | |
998 else{ | |
999 int idx = 1; | |
1000 char[] sigElement = nextSingleCompleteTypeSig( sigText, idx ); | |
1001 DBusVariantArray res = new DBusVariantArray( sigElement ); | |
1002 | |
1003 DBusMessageIter subIter; | |
1004 dbus_message_iter_recurse( iter, &subIter ); | |
1005 dbus_message_iter_next( iter ); | |
1006 | |
1007 while( dbus_message_iter_get_arg_type( &subIter ) != DBUS_TYPE_INVALID ){ | |
1008 DBusMessageIter entry; | |
1009 dbus_message_iter_recurse( &subIter, &entry ); | |
1010 dbus_message_iter_next( &subIter ); | |
1011 res.values ~= createDBusVariant( & subIter, sigElement ); | |
1012 } | |
1013 return res; | |
1014 } | |
1015 } | |
1016 else if( sigText[0] == '(' ){ | |
1017 | |
1018 DBusVariantStruct res = new DBusVariantStruct(); | |
1019 | |
1020 int idx = 1; | |
1021 ensure( sigText.length > idx, "createDBusVariant 2" ); | |
1022 | |
1023 DBusMessageIter subIter; | |
1024 dbus_message_iter_recurse( iter, &subIter ); | |
1025 dbus_message_iter_next( iter ); | |
1026 | |
1027 while( sigText[ idx ] != ')' ){ | |
1028 char[] sigElement = nextSingleCompleteTypeSig( sigText, idx ); | |
1029 ensure( sigText.length > idx, "createDBusVariant 3" ); | |
1030 res.values ~= createDBusVariant( & subIter, sigElement ); | |
1031 } | |
1032 return res; | |
1033 } | |
1034 assert(false); | |
1035 } | |
1036 | |
1037 T getVariantAsKnownType( T )( DBusVariant var ){ | |
1038 T res; | |
1039 static if( false ){} | |
1040 else static if( isAssocArrayType!(T) ){ | |
1041 version(CD) pragma( msg, "getVariantAsKnownType: assoc "~typeof(T).stringof ); | |
1042 DBusVariantMap map = cast(DBusVariantMap)var; | |
1043 ensure( map !is null, "getVariantAsKnownType map is null" ); | |
1044 typeof(T.keys [0]) k; | |
1045 typeof(T.values[0]) v; | |
1046 foreach( value; map.values ){ | |
1047 k = getVariantAsKnownType!( typeof(T.keys [0]) )( value.key ); | |
1048 v = getVariantAsKnownType!( typeof(T.values[0]) )( value.value ); | |
1049 res[ k ] = v; | |
1050 } | |
1051 } | |
1052 else static if( is( T == char[] )){ // char[] nicht als dyn array, sondern als String | |
1053 version(CD) pragma( msg, "getVariantAsKnownType: string "~typeof(T).stringof ); | |
1054 DBusVariantValueString str = cast(DBusVariantValueString)var; | |
1055 ensure( str !is null, "getVariantAsKnownType string is null" ); | |
1056 res = str.value; | |
1057 } | |
1058 else static if( isDynamicArrayType!(T) ){ | |
1059 version(CD) pragma( msg, "getVariantAsKnownType: [] "~typeof(T).stringof ); | |
1060 DBusVariantArray arr = cast(DBusVariantArray)var; | |
1061 ensure( arr !is null, "getVariantAsKnownType array is null" ); | |
1062 res = new typeof(T[0])[ arr.values.length ]; | |
1063 foreach( idx, value; arr.values ){ | |
1064 res[ idx ] = getVariantAsKnownType!( typeof(T[0]) )( value ); | |
1065 } | |
1066 } | |
1067 else static if( isDBusSimpleType!(T) ) { | |
1068 DBusVariantValue!(T) v = cast(DBusVariantValue!(T))var; | |
1069 ensure( v !is null, "getVariantAsKnownType value is null" ); | |
1070 res = v.value; | |
1071 } | |
1072 else static if( is( T : DBusObjectImpl )){ | |
1073 static assert( false ); | |
1074 } | |
1075 else static if( is( T == DBusVariant ) ){ | |
1076 res = var; | |
1077 } | |
1078 else static if( is( T == Struct!(typeof(T.t)) ) ){ | |
1079 DBusVariantStruct v = cast(DBusVariantStruct)var; | |
1080 ensure( v !is null, "getVariantAsKnownType isnull" ); | |
1081 foreach( idx, item; res.t ){ | |
1082 res.t[idx] = getVariantAsKnownType!( typeof(item) )( v.values[idx] ); | |
1083 } | |
1084 } | |
1085 else{ | |
1086 pragma( msg, "appendItem: "~typeof(t).stringof ); | |
1087 static assert(false, typeof(t).stringof ); | |
1088 } | |
1089 return res; | |
1090 } | |
1091 | |
1092 | |
1093 | |
1094 | |
1095 void testTemplateCompilation(){ | |
1096 getCallValues!( int[] )( null ); | |
1097 getCallValues!( int[ char[] ] )( null ); | |
1098 getCallValues!( DBusVariant[ DBusVariant ] )( null ); | |
1099 getCallValues!( Struct!( int[], long, char[], Struct!( bool ) ) )( null ); | |
1100 | |
1101 getVariantAsKnownType!( int[] )( null ); | |
1102 getVariantAsKnownType!( int[ char[] ] )( null ); | |
1103 getVariantAsKnownType!( DBusVariant[ DBusVariant ] )( null ); | |
1104 getVariantAsKnownType!( Struct!( int[], long, char[], Struct!( bool ) ) )( null ); | |
1105 } | |
1106 | |
1107 |