1require 'dl'
2
3module DL
4  module ValueUtil
5    def unsigned_value(val, ty)
6      case ty.abs
7      when TYPE_CHAR
8        [val].pack("c").unpack("C")[0]
9      when TYPE_SHORT
10        [val].pack("s!").unpack("S!")[0]
11      when TYPE_INT
12        [val].pack("i!").unpack("I!")[0]
13      when TYPE_LONG
14        [val].pack("l!").unpack("L!")[0]
15      when TYPE_LONG_LONG
16        [val].pack("q").unpack("Q")[0]
17      else
18        val
19      end
20    end
21
22    def signed_value(val, ty)
23      case ty.abs
24      when TYPE_CHAR
25        [val].pack("C").unpack("c")[0]
26      when TYPE_SHORT
27        [val].pack("S!").unpack("s!")[0]
28      when TYPE_INT
29        [val].pack("I!").unpack("i!")[0]
30      when TYPE_LONG
31        [val].pack("L!").unpack("l!")[0]
32      when TYPE_LONG_LONG
33        [val].pack("Q").unpack("q")[0]
34      else
35        val
36      end
37    end
38
39    def wrap_args(args, tys, funcs, &block)
40      result = []
41      tys ||= []
42      args.each_with_index{|arg, idx|
43        result.push(wrap_arg(arg, tys[idx], funcs, &block))
44      }
45      result
46    end
47
48    def wrap_arg(arg, ty, funcs = [], &block)
49        require 'dl/func'
50
51        funcs ||= []
52        case arg
53        when nil
54          return 0
55        when CPtr
56          return arg.to_i
57        when IO
58          case ty
59          when TYPE_VOIDP
60            return CPtr[arg].to_i
61          else
62            return arg.to_i
63          end
64        when Function
65          if( block )
66            arg.bind_at_call(&block)
67            funcs.push(arg)
68          elsif !arg.bound?
69            raise(RuntimeError, "block must be given.")
70          end
71          return arg.to_i
72        when String
73          if( ty.is_a?(Array) )
74            return arg.unpack('C*')
75          else
76            case SIZEOF_VOIDP
77            when SIZEOF_LONG
78              return [arg].pack("p").unpack("l!")[0]
79            when SIZEOF_LONG_LONG
80              return [arg].pack("p").unpack("q")[0]
81            else
82              raise(RuntimeError, "sizeof(void*)?")
83            end
84          end
85        when Float, Integer
86          return arg
87        when Array
88          if( ty.is_a?(Array) ) # used only by struct
89            case ty[0]
90            when TYPE_VOIDP
91              return arg.collect{|v| Integer(v)}
92            when TYPE_CHAR
93              if( arg.is_a?(String) )
94                return val.unpack('C*')
95              end
96            end
97            return arg
98          else
99            return arg
100          end
101        else
102          if( arg.respond_to?(:to_ptr) )
103            return arg.to_ptr.to_i
104          else
105            begin
106              return Integer(arg)
107            rescue
108              raise(ArgumentError, "unknown argument type: #{arg.class}")
109            end
110          end
111        end
112    end
113  end
114end
115