ruby-dbus 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/NEWS +13 -0
- data/{README → README.md} +10 -10
- data/Rakefile +4 -12
- data/VERSION +1 -1
- data/doc/Reference.md +196 -0
- data/doc/{tutorial/index.markdown → Tutorial.md} +0 -0
- data/doc/ex-calling-methods.body.rb +8 -0
- data/doc/ex-calling-methods.rb +3 -0
- data/doc/ex-properties.body.rb +9 -0
- data/doc/ex-properties.rb +3 -0
- data/doc/ex-setup.rb +7 -0
- data/doc/ex-signal.body.rb +20 -0
- data/doc/ex-signal.rb +3 -0
- data/doc/example-helper.rb +6 -0
- data/lib/dbus.rb +2 -1
- data/lib/dbus/auth.rb +10 -12
- data/lib/dbus/bus.rb +17 -12
- data/lib/dbus/introspect.rb +92 -41
- data/lib/dbus/logger.rb +31 -0
- data/lib/dbus/message.rb +16 -58
- data/lib/dbus/type.rb +32 -64
- data/lib/dbus/xml.rb +4 -2
- data/ruby-dbus.gemspec +3 -3
- data/test/bus_driver_test.rb +0 -4
- data/test/introspection_test.rb +31 -0
- data/test/service_newapi.rb +16 -9
- data/test/session_bus_test_manual.rb +0 -4
- data/test/signal_test.rb +34 -9
- data/test/t6-loop.rb +5 -9
- data/test/thread_safety_test.rb +0 -4
- data/test/type_test.rb +22 -0
- metadata +36 -43
data/lib/dbus/bus.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
# This file is part of the ruby-dbus project
|
4
4
|
# Copyright (C) 2007 Arnaud Cornet and Paul van Tilburg
|
5
5
|
#
|
6
|
-
# This library is free software; you
|
6
|
+
# This library is free software; you caan redistribute it and/or
|
7
7
|
# modify it under the terms of the GNU Lesser General Public
|
8
8
|
# License, version 2.1 as published by the Free Software Foundation.
|
9
9
|
# See the file "COPYING" for the exact licensing terms.
|
@@ -49,7 +49,8 @@ module DBus
|
|
49
49
|
self
|
50
50
|
end
|
51
51
|
|
52
|
-
# Retrieves an object
|
52
|
+
# Retrieves an object at the given _path_.
|
53
|
+
# @return [ProxyObject]
|
53
54
|
def object(path)
|
54
55
|
node = get_node(path, true)
|
55
56
|
if node.object.nil?
|
@@ -95,7 +96,7 @@ module DBus
|
|
95
96
|
n = n[elem]
|
96
97
|
end
|
97
98
|
if n.nil?
|
98
|
-
|
99
|
+
DBus.logger.debug "Warning, unknown object #{path}"
|
99
100
|
end
|
100
101
|
n
|
101
102
|
end
|
@@ -248,7 +249,7 @@ module DBus
|
|
248
249
|
@is_tcp = true
|
249
250
|
rescue
|
250
251
|
puts "Error: Could not establish connection to: #{@path}, will now exit."
|
251
|
-
exit(
|
252
|
+
exit(1) #a little harsh
|
252
253
|
end
|
253
254
|
else
|
254
255
|
#Danger, Will Robinson: the specified "path" is not usable
|
@@ -469,6 +470,7 @@ module DBus
|
|
469
470
|
#
|
470
471
|
# FIXME, NameRequestError cannot really be rescued as it will be raised
|
471
472
|
# when dispatching a later call. Rework the API to better match the spec.
|
473
|
+
# @return [Service]
|
472
474
|
def request_service(name)
|
473
475
|
# Use RequestName, but asynchronously!
|
474
476
|
# A synchronous call would not work with service activation, where
|
@@ -598,10 +600,10 @@ module DBus
|
|
598
600
|
def add_match(mr, &slot)
|
599
601
|
# check this is a signal.
|
600
602
|
mrs = mr.to_s
|
601
|
-
|
603
|
+
DBus.logger.debug "#{@signal_matchrules.size} rules, adding #{mrs.inspect}"
|
602
604
|
# don't ask for the same match if we override it
|
603
605
|
unless @signal_matchrules.key?(mrs)
|
604
|
-
|
606
|
+
DBus.logger.debug "Asked for a new match"
|
605
607
|
proxy.AddMatch(mrs)
|
606
608
|
end
|
607
609
|
@signal_matchrules[mrs] = slot
|
@@ -625,7 +627,7 @@ module DBus
|
|
625
627
|
raise InvalidPacketException if m.reply_serial == nil
|
626
628
|
mcs = @method_call_replies[m.reply_serial]
|
627
629
|
if not mcs
|
628
|
-
|
630
|
+
DBus.logger.debug "no return code for mcs: #{mcs.inspect} m: #{m.inspect}"
|
629
631
|
else
|
630
632
|
if m.message_type == Message::ERROR
|
631
633
|
mcs.call(Error.new(m))
|
@@ -637,7 +639,7 @@ module DBus
|
|
637
639
|
end
|
638
640
|
when DBus::Message::METHOD_CALL
|
639
641
|
if m.path == "/org/freedesktop/DBus"
|
640
|
-
|
642
|
+
DBus.logger.debug "Got method call on /org/freedesktop/DBus"
|
641
643
|
end
|
642
644
|
node = @service.get_node(m.path)
|
643
645
|
if not node
|
@@ -664,11 +666,12 @@ module DBus
|
|
664
666
|
end
|
665
667
|
end
|
666
668
|
else
|
667
|
-
|
669
|
+
DBus.logger.debug "Unknown message type: #{m.message_type}"
|
668
670
|
end
|
669
671
|
end
|
670
672
|
|
671
673
|
# Retrieves the Service with the given _name_.
|
674
|
+
# @return [Service]
|
672
675
|
def service(name)
|
673
676
|
# The service might not exist at this time so we cannot really check
|
674
677
|
# anything
|
@@ -704,7 +707,7 @@ module DBus
|
|
704
707
|
m.member = "Hello"
|
705
708
|
send_sync(m) do |rmsg|
|
706
709
|
@unique_name = rmsg.destination
|
707
|
-
|
710
|
+
DBus.logger.debug "Got hello reply. Our unique_name is #{@unique_name}"
|
708
711
|
end
|
709
712
|
@service = Service.new(@unique_name, self)
|
710
713
|
end
|
@@ -794,12 +797,14 @@ module DBus
|
|
794
797
|
include Singleton
|
795
798
|
end
|
796
799
|
|
797
|
-
# Shortcut for the SystemBus instance
|
800
|
+
# Shortcut for the {SystemBus} instance
|
801
|
+
# @return [Connection]
|
798
802
|
def DBus.system_bus
|
799
803
|
SystemBus.instance
|
800
804
|
end
|
801
805
|
|
802
|
-
# Shortcut for the SessionBus instance
|
806
|
+
# Shortcut for the {SessionBus} instance
|
807
|
+
# @return [Connection]
|
803
808
|
def DBus.session_bus
|
804
809
|
SessionBus.instance
|
805
810
|
end
|
data/lib/dbus/introspect.rb
CHANGED
@@ -247,50 +247,34 @@ module DBus
|
|
247
247
|
(class << self ; self ; end)
|
248
248
|
end
|
249
249
|
|
250
|
-
# FIXME
|
251
|
-
def check_for_eval(s)
|
252
|
-
raise RuntimeError, "invalid internal data '#{s}'" if not s.to_s =~ /^[A-Za-z0-9_]*$/
|
253
|
-
end
|
254
|
-
|
255
|
-
# FIXME
|
256
|
-
def check_for_quoted_eval(s)
|
257
|
-
raise RuntimeError, "invalid internal data '#{s}'" if not s.to_s =~ /^[^"]+$/
|
258
|
-
end
|
259
|
-
|
260
250
|
# Defines a method on the interface from the Method descriptor _m_.
|
261
251
|
def define_method_from_descriptor(m)
|
262
|
-
check_for_eval(m.name)
|
263
|
-
check_for_quoted_eval(@name)
|
264
|
-
methdef = "def #{m.name}("
|
265
|
-
methdef += (0..(m.params.size - 1)).to_a.collect { |n|
|
266
|
-
"arg#{n}"
|
267
|
-
}.push("&reply_handler").join(", ")
|
268
|
-
methdef += %{)
|
269
|
-
msg = Message.new(Message::METHOD_CALL)
|
270
|
-
msg.path = @object.path
|
271
|
-
msg.interface = "#{@name}"
|
272
|
-
msg.destination = @object.destination
|
273
|
-
msg.member = "#{m.name}"
|
274
|
-
msg.sender = @object.bus.unique_name
|
275
|
-
}
|
276
|
-
idx = 0
|
277
252
|
m.params.each do |fpar|
|
278
253
|
par = fpar.type
|
279
|
-
check_for_quoted_eval(par)
|
280
|
-
|
281
254
|
# This is the signature validity check
|
282
255
|
Type::Parser.new(par).parse
|
283
|
-
|
284
|
-
methdef += %{
|
285
|
-
msg.add_param("#{par}", arg#{idx})
|
286
|
-
}
|
287
|
-
idx += 1
|
288
256
|
end
|
289
|
-
|
290
|
-
|
257
|
+
|
258
|
+
singleton_class.class_eval do
|
259
|
+
define_method m.name do |*args, &reply_handler|
|
260
|
+
if m.params.size != args.size
|
261
|
+
raise ArgumentError, "wrong number of arguments (#{args.size} for #{m.params.size})"
|
262
|
+
end
|
263
|
+
|
264
|
+
msg = Message.new(Message::METHOD_CALL)
|
265
|
+
msg.path = @object.path
|
266
|
+
msg.interface = @name
|
267
|
+
msg.destination = @object.destination
|
268
|
+
msg.member = m.name
|
269
|
+
msg.sender = @object.bus.unique_name
|
270
|
+
m.params.each do |fpar|
|
271
|
+
par = fpar.type
|
272
|
+
msg.add_param(par, args.shift)
|
273
|
+
end
|
274
|
+
@object.bus.send_sync_or_async(msg, &reply_handler)
|
275
|
+
end
|
291
276
|
end
|
292
|
-
|
293
|
-
singleton_class.class_eval(methdef)
|
277
|
+
|
294
278
|
@methods[m.name] = m
|
295
279
|
end
|
296
280
|
|
@@ -315,9 +299,25 @@ module DBus
|
|
315
299
|
define(m)
|
316
300
|
end
|
317
301
|
|
302
|
+
# @overload on_signal(name, &block)
|
303
|
+
# @overload on_signal(bus, name, &block)
|
318
304
|
# Registers a handler (code block) for a signal with _name_ arriving
|
319
305
|
# over the given _bus_. If no block is given, the signal is unregistered.
|
320
|
-
|
306
|
+
# Note that specifying _bus_ is discouraged and the option is kept only for
|
307
|
+
# backward compatibility.
|
308
|
+
# @return [void]
|
309
|
+
def on_signal(*args, &block)
|
310
|
+
# Since we must function under ruby 1.8.7, it isn't possible to define the
|
311
|
+
# function as on_signal(bus = nil, name, &block)
|
312
|
+
bus = case args.size
|
313
|
+
when 1
|
314
|
+
@object.bus
|
315
|
+
when 2
|
316
|
+
args.shift
|
317
|
+
else
|
318
|
+
raise ArgumentError, "wrong number of arguments (#{args.size} for 1-2)"
|
319
|
+
end
|
320
|
+
name = args.shift
|
321
321
|
mr = DBus::MatchRule.new.from_signal(self, name)
|
322
322
|
if block.nil?
|
323
323
|
bus.remove_match(mr)
|
@@ -339,6 +339,7 @@ module DBus
|
|
339
339
|
end
|
340
340
|
|
341
341
|
# Read all properties at once, as a hash.
|
342
|
+
# @return [Hash{String}]
|
342
343
|
def all_properties
|
343
344
|
self.object[PROPERTY_INTERFACE].GetAll(self.name)[0]
|
344
345
|
end
|
@@ -361,7 +362,7 @@ module DBus
|
|
361
362
|
attr_reader :path
|
362
363
|
# The bus the object is reachable via.
|
363
364
|
attr_reader :bus
|
364
|
-
# The default interface of the object
|
365
|
+
# @return [String] The name of the default interface of the object.
|
365
366
|
attr_accessor :default_iface
|
366
367
|
|
367
368
|
# Creates a new proxy object living on the given _bus_ at destination _dest_
|
@@ -377,25 +378,69 @@ module DBus
|
|
377
378
|
@interfaces.keys
|
378
379
|
end
|
379
380
|
|
380
|
-
# Retrieves an interface of the proxy object
|
381
|
+
# Retrieves an interface of the proxy object
|
382
|
+
# @param [String] intfname
|
383
|
+
# @return [ProxyObjectInterface]
|
381
384
|
def [](intfname)
|
382
385
|
@interfaces[intfname]
|
383
386
|
end
|
384
387
|
|
385
388
|
# Maps the given interface name _intfname_ to the given interface _intf.
|
389
|
+
# @param [String] intfname
|
390
|
+
# @param [ProxyObjectInterface] intf
|
391
|
+
# @return [ProxyObjectInterface]
|
386
392
|
def []=(intfname, intf)
|
387
393
|
@interfaces[intfname] = intf
|
388
394
|
end
|
389
395
|
|
390
|
-
# Introspects the remote object.
|
396
|
+
# Introspects the remote object. Allows you to find and select
|
391
397
|
# interfaces on the object.
|
392
398
|
def introspect
|
393
399
|
# Synchronous call here.
|
394
400
|
xml = @bus.introspect_data(@destination, @path)
|
395
401
|
ProxyObjectFactory.introspect_into(self, xml)
|
402
|
+
define_shortcut_methods()
|
396
403
|
xml
|
397
404
|
end
|
398
405
|
|
406
|
+
# For each non duplicated method name in any interface present on the
|
407
|
+
# caller, defines a shortcut method dynamically.
|
408
|
+
# This function is automatically called when a {ProxyObject} is
|
409
|
+
# introspected.
|
410
|
+
def define_shortcut_methods
|
411
|
+
# builds a list of duplicated methods
|
412
|
+
dup_meths, univocal_meths = [],{}
|
413
|
+
@interfaces.each_value do |intf|
|
414
|
+
intf.methods.each_value do |meth|
|
415
|
+
# Module#instance_methods give us an array of symbols or strings,
|
416
|
+
# depending on which version
|
417
|
+
name = if RUBY_VERSION >= "1.9"
|
418
|
+
meth.name.to_sym
|
419
|
+
else
|
420
|
+
meth.name
|
421
|
+
end
|
422
|
+
# don't overwrite instance methods!
|
423
|
+
if dup_meths.include? name or self.class.instance_methods.include? name
|
424
|
+
next
|
425
|
+
elsif univocal_meths.include? name
|
426
|
+
univocal_meths.delete name
|
427
|
+
dup_meths << name
|
428
|
+
else
|
429
|
+
univocal_meths[name] = intf
|
430
|
+
end
|
431
|
+
end
|
432
|
+
end
|
433
|
+
univocal_meths.each do |name, intf|
|
434
|
+
# creates a shortcut function that forwards each call to the method on
|
435
|
+
# the appropriate intf
|
436
|
+
singleton_class.class_eval do
|
437
|
+
define_method name do |*args, &reply_handler|
|
438
|
+
intf.method(name).call(*args, &reply_handler)
|
439
|
+
end
|
440
|
+
end
|
441
|
+
end
|
442
|
+
end
|
443
|
+
|
399
444
|
# Returns whether the object has an interface with the given _name_.
|
400
445
|
def has_iface?(name)
|
401
446
|
raise "Cannot call has_iface? if not introspected" if not @introspected
|
@@ -404,9 +449,10 @@ module DBus
|
|
404
449
|
|
405
450
|
# Registers a handler, the code block, for a signal with the given _name_.
|
406
451
|
# It uses _default_iface_ which must have been set.
|
452
|
+
# @return [void]
|
407
453
|
def on_signal(name, &block)
|
408
454
|
if @default_iface and has_iface?(@default_iface)
|
409
|
-
@interfaces[@default_iface].on_signal(
|
455
|
+
@interfaces[@default_iface].on_signal(name, &block)
|
410
456
|
else
|
411
457
|
# TODO improve
|
412
458
|
raise NoMethodError
|
@@ -437,6 +483,11 @@ module DBus
|
|
437
483
|
raise NoMethodError, "undefined method `#{name}' for DBus interface `#{@default_iface}' on object `#{@path}'"
|
438
484
|
end
|
439
485
|
end
|
486
|
+
|
487
|
+
# Returns the singleton class of the object.
|
488
|
+
def singleton_class
|
489
|
+
(class << self ; self ; end)
|
490
|
+
end
|
440
491
|
end # class ProxyObject
|
441
492
|
|
442
493
|
# = D-Bus proxy object factory class
|
data/lib/dbus/logger.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# dbus/logger.rb - debug logging
|
2
|
+
#
|
3
|
+
# This file is part of the ruby-dbus project
|
4
|
+
# Copyright (C) 2012 Martin Vidner
|
5
|
+
#
|
6
|
+
# This library is free software; you can redistribute it and/or
|
7
|
+
# modify it under the terms of the GNU Lesser General Public
|
8
|
+
# License, version 2.1 as published by the Free Software Foundation.
|
9
|
+
# See the file "COPYING" for the exact licensing terms.
|
10
|
+
|
11
|
+
require 'logger'
|
12
|
+
|
13
|
+
module DBus
|
14
|
+
# Get the logger for the DBus module.
|
15
|
+
# The default one logs to STDERR,
|
16
|
+
# with DEBUG if $DEBUG is set, otherwise INFO.
|
17
|
+
def logger
|
18
|
+
unless defined? @logger
|
19
|
+
@logger = Logger.new(STDERR)
|
20
|
+
@logger.level = $DEBUG ? Logger::DEBUG : Logger::INFO
|
21
|
+
end
|
22
|
+
@logger
|
23
|
+
end
|
24
|
+
module_function :logger
|
25
|
+
|
26
|
+
# Set the logger for the DBus module
|
27
|
+
def logger=(logger)
|
28
|
+
@logger = logger
|
29
|
+
end
|
30
|
+
module_function :logger=
|
31
|
+
end
|
data/lib/dbus/message.rb
CHANGED
@@ -101,6 +101,10 @@ module DBus
|
|
101
101
|
end
|
102
102
|
end
|
103
103
|
|
104
|
+
def to_s
|
105
|
+
"#{message_type} sender=#{sender} -> dest=#{destination} serial=#{serial} reply_serial=#{reply_serial} path=#{path}; interface=#{interface}; member=#{member} error_name=#{error_name}"
|
106
|
+
end
|
107
|
+
|
104
108
|
# Create a regular reply to a message _m_.
|
105
109
|
def self.method_return(m)
|
106
110
|
MethodReturnMessage.new.reply_to(m)
|
@@ -161,64 +165,18 @@ module DBus
|
|
161
165
|
marshaller.append(Type::BYTE, @protocol)
|
162
166
|
marshaller.append(Type::UINT32, @body_length)
|
163
167
|
marshaller.append(Type::UINT32, @serial)
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
marshaller.append(Type::BYTE, 1)
|
177
|
-
marshaller.append_simple_string("s")
|
178
|
-
marshaller.append(Type::STRING, @interface)
|
179
|
-
end
|
180
|
-
end
|
181
|
-
if @member
|
182
|
-
marshaller.struct do
|
183
|
-
marshaller.append(Type::BYTE, MEMBER)
|
184
|
-
marshaller.append(Type::BYTE, 1)
|
185
|
-
marshaller.append_simple_string("s")
|
186
|
-
marshaller.append(Type::STRING, @member)
|
187
|
-
end
|
188
|
-
end
|
189
|
-
if @error_name
|
190
|
-
marshaller.struct do
|
191
|
-
marshaller.append(Type::BYTE, ERROR_NAME)
|
192
|
-
marshaller.append(Type::BYTE, 1)
|
193
|
-
marshaller.append_simple_string("s")
|
194
|
-
marshaller.append(Type::STRING, @error_name)
|
195
|
-
end
|
196
|
-
end
|
197
|
-
if @reply_serial
|
198
|
-
marshaller.struct do
|
199
|
-
marshaller.append(Type::BYTE, REPLY_SERIAL)
|
200
|
-
marshaller.append(Type::BYTE, 1)
|
201
|
-
marshaller.append_simple_string("u")
|
202
|
-
marshaller.append(Type::UINT32, @reply_serial)
|
203
|
-
end
|
204
|
-
end
|
205
|
-
if @destination
|
206
|
-
marshaller.struct do
|
207
|
-
marshaller.append(Type::BYTE, DESTINATION)
|
208
|
-
marshaller.append(Type::BYTE, 1)
|
209
|
-
marshaller.append_simple_string("s")
|
210
|
-
marshaller.append(Type::STRING, @destination)
|
211
|
-
end
|
212
|
-
end
|
213
|
-
if @signature != ""
|
214
|
-
marshaller.struct do
|
215
|
-
marshaller.append(Type::BYTE, SIGNATURE)
|
216
|
-
marshaller.append(Type::BYTE, 1)
|
217
|
-
marshaller.append_simple_string("g")
|
218
|
-
marshaller.append(Type::SIGNATURE, @signature)
|
219
|
-
end
|
220
|
-
end
|
221
|
-
end
|
168
|
+
|
169
|
+
headers = []
|
170
|
+
headers << [PATH, ["o", @path]] if @path
|
171
|
+
headers << [INTERFACE, ["s", @interface]] if @interface
|
172
|
+
headers << [MEMBER, ["s", @member]] if @member
|
173
|
+
headers << [ERROR_NAME, ["s", @error_name]] if @error_name
|
174
|
+
headers << [REPLY_SERIAL, ["u", @reply_serial]] if @reply_serial
|
175
|
+
headers << [DESTINATION, ["s", @destination]] if @destination
|
176
|
+
# SENDER is not sent, the message bus fills it in instead
|
177
|
+
headers << [SIGNATURE, ["g", @signature]] if @signature != ""
|
178
|
+
marshaller.append("a(yv)", headers)
|
179
|
+
|
222
180
|
marshaller.align(8)
|
223
181
|
@params.each do |param|
|
224
182
|
marshaller.append(param[0], param[1])
|
data/lib/dbus/type.rb
CHANGED
@@ -15,47 +15,31 @@ module DBus
|
|
15
15
|
# This module containts the constants of the types specified in the D-Bus
|
16
16
|
# protocol.
|
17
17
|
module Type
|
18
|
-
#
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
# Mapping from type number to name.
|
39
|
-
TypeName = {
|
40
|
-
INVALID => "INVALID",
|
41
|
-
BYTE => "BYTE",
|
42
|
-
BOOLEAN => "BOOLEAN",
|
43
|
-
INT16 => "INT16",
|
44
|
-
UINT16 => "UINT16",
|
45
|
-
INT32 => "INT32",
|
46
|
-
UINT32 => "UINT32",
|
47
|
-
INT64 => "INT64",
|
48
|
-
UINT64 => "UINT64",
|
49
|
-
DOUBLE => "DOUBLE",
|
50
|
-
STRUCT => "STRUCT",
|
51
|
-
ARRAY => "ARRAY",
|
52
|
-
VARIANT => "VARIANT",
|
53
|
-
OBJECT_PATH => "OBJECT_PATH",
|
54
|
-
STRING => "STRING",
|
55
|
-
SIGNATURE => "SIGNATURE",
|
56
|
-
DICT_ENTRY => "DICT_ENTRY",
|
57
|
-
UNIX_FD => "UNIX_FD"
|
18
|
+
# Mapping from type number to name and alignment.
|
19
|
+
TypeMapping = {
|
20
|
+
0 => ["INVALID", nil],
|
21
|
+
?y => ["BYTE", 1],
|
22
|
+
?b => ["BOOLEAN", 4],
|
23
|
+
?n => ["INT16", 2],
|
24
|
+
?q => ["UINT16", 2],
|
25
|
+
?i => ["INT32", 4],
|
26
|
+
?u => ["UINT32", 4],
|
27
|
+
?x => ["INT64", 8],
|
28
|
+
?t => ["UINT64", 8],
|
29
|
+
?d => ["DOUBLE", 8],
|
30
|
+
?r => ["STRUCT", 8],
|
31
|
+
?a => ["ARRAY", 4],
|
32
|
+
?v => ["VARIANT", 1],
|
33
|
+
?o => ["OBJECT_PATH", 4],
|
34
|
+
?s => ["STRING", 4],
|
35
|
+
?g => ["SIGNATURE", 1],
|
36
|
+
?e => ["DICT_ENTRY", 8],
|
37
|
+
?h => ["UNIX_FD", 4],
|
58
38
|
}
|
39
|
+
# Defines the set of constants
|
40
|
+
TypeMapping.each_pair do |key, value|
|
41
|
+
Type.const_set(value.first, key)
|
42
|
+
end
|
59
43
|
|
60
44
|
# Exception raised when an unknown/incorrect type is encountered.
|
61
45
|
class SignatureException < Exception
|
@@ -72,7 +56,7 @@ module Type
|
|
72
56
|
|
73
57
|
# Create a new type instance for type number _sigtype_.
|
74
58
|
def initialize(sigtype)
|
75
|
-
if not
|
59
|
+
if not TypeMapping.keys.member?(sigtype)
|
76
60
|
raise SignatureException, "Unknown key in signature: #{sigtype.chr}"
|
77
61
|
end
|
78
62
|
@sigtype = sigtype
|
@@ -81,25 +65,7 @@ module Type
|
|
81
65
|
|
82
66
|
# Return the required alignment for the type.
|
83
67
|
def alignment
|
84
|
-
|
85
|
-
BYTE => 1,
|
86
|
-
BOOLEAN => 4,
|
87
|
-
INT16 => 2,
|
88
|
-
UINT16 => 2,
|
89
|
-
INT32 => 4,
|
90
|
-
UINT32 => 4,
|
91
|
-
INT64 => 8,
|
92
|
-
UINT64 => 8,
|
93
|
-
STRUCT => 8,
|
94
|
-
DICT_ENTRY => 8,
|
95
|
-
DOUBLE => 8,
|
96
|
-
ARRAY => 4,
|
97
|
-
VARIANT => 1,
|
98
|
-
OBJECT_PATH => 4,
|
99
|
-
STRING => 4,
|
100
|
-
SIGNATURE => 1,
|
101
|
-
UNIX_FD => 4,
|
102
|
-
}[@sigtype]
|
68
|
+
TypeMapping[@sigtype].last
|
103
69
|
end
|
104
70
|
|
105
71
|
# Return a string representation of the type according to the
|
@@ -113,7 +79,7 @@ module Type
|
|
113
79
|
when DICT_ENTRY
|
114
80
|
"{" + @members.collect { |t| t.to_s }.join + "}"
|
115
81
|
else
|
116
|
-
if not
|
82
|
+
if not TypeMapping.keys.member?(@sigtype)
|
117
83
|
raise NotImplementedError
|
118
84
|
end
|
119
85
|
@sigtype.chr
|
@@ -123,7 +89,7 @@ module Type
|
|
123
89
|
# Add a new member type _a_.
|
124
90
|
def <<(a)
|
125
91
|
if not [STRUCT, ARRAY, DICT_ENTRY].member?(@sigtype)
|
126
|
-
raise SignatureException
|
92
|
+
raise SignatureException
|
127
93
|
end
|
128
94
|
raise SignatureException if @sigtype == ARRAY and @members.size > 0
|
129
95
|
if @sigtype == DICT_ENTRY
|
@@ -145,7 +111,7 @@ module Type
|
|
145
111
|
end
|
146
112
|
|
147
113
|
def inspect
|
148
|
-
s =
|
114
|
+
s = TypeMapping[@sigtype].first
|
149
115
|
if [STRUCT, ARRAY].member?(@sigtype)
|
150
116
|
s += ": " + @members.inspect
|
151
117
|
end
|
@@ -176,7 +142,9 @@ module Type
|
|
176
142
|
case c
|
177
143
|
when ?a
|
178
144
|
res = Type.new(ARRAY)
|
179
|
-
|
145
|
+
c = nextchar
|
146
|
+
raise SignatureException, "Parse error in #{@signature}" if c == nil
|
147
|
+
child = parse_one(c)
|
180
148
|
res << child
|
181
149
|
when ?(
|
182
150
|
res = Type.new(STRUCT)
|