1require 'fiddle'
2
3module Fiddle
4  module ValueUtil #:nodoc: all
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      funcs ||= []
50      case arg
51      when nil
52        return 0
53      when Pointer
54        return arg.to_i
55      when IO
56        case ty
57        when TYPE_VOIDP
58          return Pointer[arg].to_i
59        else
60          return arg.to_i
61        end
62      when Function
63        if( block )
64          arg.bind_at_call(&block)
65          funcs.push(arg)
66        elsif !arg.bound?
67          raise(RuntimeError, "block must be given.")
68        end
69        return arg.to_i
70      when String
71        if( ty.is_a?(Array) )
72          return arg.unpack('C*')
73        else
74          case SIZEOF_VOIDP
75          when SIZEOF_LONG
76            return [arg].pack("p").unpack("l!")[0]
77          when SIZEOF_LONG_LONG
78            return [arg].pack("p").unpack("q")[0]
79          else
80            raise(RuntimeError, "sizeof(void*)?")
81          end
82        end
83      when Float, Integer
84        return arg
85      when Array
86        if( ty.is_a?(Array) ) # used only by struct
87          case ty[0]
88          when TYPE_VOIDP
89            return arg.collect{|v| Integer(v)}
90          when TYPE_CHAR
91            if( arg.is_a?(String) )
92              return val.unpack('C*')
93            end
94          end
95          return arg
96        else
97          return arg
98        end
99      else
100        if( arg.respond_to?(:to_ptr) )
101          return arg.to_ptr.to_i
102        else
103          begin
104            return Integer(arg)
105          rescue
106            raise(ArgumentError, "unknown argument type: #{arg.class}")
107          end
108        end
109      end
110    end
111  end
112end
113