1require 'dl' 2 3module DL 4 class Stack 5 def self.[](*types) 6 new(types) 7 end 8 9 def initialize(types) 10 parse_types(types) 11 end 12 13 def size() 14 @size 15 end 16 17 def types() 18 @types 19 end 20 21 def pack(ary) 22 case SIZEOF_VOIDP 23 when SIZEOF_LONG 24 ary.pack(@template).unpack('l!*') 25 when SIZEOF_LONG_LONG 26 ary.pack(@template).unpack('q*') 27 else 28 raise(RuntimeError, "sizeof(void*)?") 29 end 30 end 31 32 def unpack(ary) 33 case SIZEOF_VOIDP 34 when SIZEOF_LONG 35 ary.pack('l!*').unpack(@template) 36 when SIZEOF_LONG_LONG 37 ary.pack('q*').unpack(@template) 38 else 39 raise(RuntimeError, "sizeof(void*)?") 40 end 41 end 42 43 private 44 45 def align(addr, align) 46 d = addr % align 47 if( d == 0 ) 48 addr 49 else 50 addr + (align - d) 51 end 52 end 53 54 ALIGN_MAP = { 55 TYPE_VOIDP => ALIGN_VOIDP, 56 TYPE_CHAR => ALIGN_VOIDP, 57 TYPE_SHORT => ALIGN_VOIDP, 58 TYPE_INT => ALIGN_VOIDP, 59 TYPE_LONG => ALIGN_VOIDP, 60 TYPE_FLOAT => ALIGN_FLOAT, 61 TYPE_DOUBLE => ALIGN_DOUBLE, 62 } 63 64 PACK_MAP = { 65 TYPE_VOIDP => ((SIZEOF_VOIDP == SIZEOF_LONG_LONG)? "q" : "l!"), 66 TYPE_CHAR => "c", 67 TYPE_SHORT => "s!", 68 TYPE_INT => "i!", 69 TYPE_LONG => "l!", 70 TYPE_FLOAT => "f", 71 TYPE_DOUBLE => "d", 72 } 73 74 SIZE_MAP = { 75 TYPE_VOIDP => SIZEOF_VOIDP, 76 TYPE_CHAR => SIZEOF_CHAR, 77 TYPE_SHORT => SIZEOF_SHORT, 78 TYPE_INT => SIZEOF_INT, 79 TYPE_LONG => SIZEOF_LONG, 80 TYPE_FLOAT => SIZEOF_FLOAT, 81 TYPE_DOUBLE => SIZEOF_DOUBLE, 82 } 83 if defined?(TYPE_LONG_LONG) 84 ALIGN_MAP[TYPE_LONG_LONG] = ALIGN_LONG_LONG 85 PACK_MAP[TYPE_LONG_LONG] = "q" 86 SIZE_MAP[TYPE_LONG_LONG] = SIZEOF_LONG_LONG 87 end 88 89 def parse_types(types) 90 @types = types 91 @template = "" 92 addr = 0 93 types.each{|t| 94 addr = add_padding(addr, ALIGN_MAP[t]) 95 @template << PACK_MAP[t] 96 addr += SIZE_MAP[t] 97 } 98 addr = add_padding(addr, ALIGN_MAP[SIZEOF_VOIDP]) 99 if( addr % SIZEOF_VOIDP == 0 ) 100 @size = addr / SIZEOF_VOIDP 101 else 102 @size = (addr / SIZEOF_VOIDP) + 1 103 end 104 end 105 106 def add_padding(addr, align) 107 orig_addr = addr 108 addr = align(orig_addr, align) 109 d = addr - orig_addr 110 if( d > 0 ) 111 @template << "x#{d}" 112 end 113 addr 114 end 115 end 116end 117