# # Copyright (C) 2008, 2009 Wayne Meissner # Copyright (C) 2009 Luc Heinrich # Copyright (c) 2007, 2008 Evan Phoenix # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright notice # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # * Neither the name of the Evan Phoenix nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. module FFI # TypeDefs = Hash.new def self.add_typedef(current, add) if current.kind_of?(FFI::Type) code = current else code = TypeDefs[current] raise TypeError, "Unable to resolve type '#{current}'" unless code end TypeDefs[add] = code end def self.find_type(name, type_map = nil) type_map = TypeDefs if type_map.nil? code = type_map[name] code = name if !code && name.kind_of?(FFI::Type) raise TypeError, "Unable to resolve type '#{name}'" unless code return code end # Converts a char add_typedef(NativeType::INT8, :char) # Converts an unsigned char add_typedef(NativeType::UINT8, :uchar) # Converts an 8 bit int add_typedef(NativeType::INT8, :int8) # Converts an unsigned char add_typedef(NativeType::UINT8, :uint8) # Converts a short add_typedef(NativeType::INT16, :short) # Converts an unsigned short add_typedef(NativeType::UINT16, :ushort) # Converts a 16bit int add_typedef(NativeType::INT16, :int16) # Converts an unsigned 16 bit int add_typedef(NativeType::UINT16, :uint16) # Converts an int add_typedef(NativeType::INT32, :int) # Converts an unsigned int add_typedef(NativeType::UINT32, :uint) # Converts a 32 bit int add_typedef(NativeType::INT32, :int32) # Converts an unsigned 16 bit int add_typedef(NativeType::UINT32, :uint32) # Converts a long add_typedef(NativeType::LONG, :long) # Converts an unsigned long add_typedef(NativeType::ULONG, :ulong) # Converts a 64 bit int add_typedef(NativeType::INT64, :int64) # Converts an unsigned 64 bit int add_typedef(NativeType::UINT64, :uint64) # Converts a long long add_typedef(NativeType::INT64, :long_long) # Converts an unsigned long long add_typedef(NativeType::UINT64, :ulong_long) # Converts a float add_typedef(NativeType::FLOAT32, :float) # Converts a double add_typedef(NativeType::FLOAT64, :double) # Converts a pointer to opaque data add_typedef(NativeType::POINTER, :pointer) # For when a function has no return value add_typedef(NativeType::VOID, :void) # Converts NUL-terminated C strings add_typedef(NativeType::STRING, :string) # Converts FFI::Buffer objects add_typedef(NativeType::BUFFER_IN, :buffer_in) add_typedef(NativeType::BUFFER_OUT, :buffer_out) add_typedef(NativeType::BUFFER_INOUT, :buffer_inout) add_typedef(NativeType::VARARGS, :varargs) add_typedef(NativeType::ENUM, :enum) add_typedef(NativeType::BOOL, :bool) # Use for a C struct with a char [] embedded inside. add_typedef(NativeType::CHAR_ARRAY, :char_array) TypeSizes = { 1 => :char, 2 => :short, 4 => :int, 8 => :long_long, } SizeTypes.merge!({ NativeType::INT8 => 1, NativeType::UINT8 => 1, NativeType::INT16 => 2, NativeType::UINT16 => 2, NativeType::INT32 => 4, NativeType::UINT32 => 4, NativeType::INT64 => 8, NativeType::UINT64 => 8, NativeType::FLOAT32 => 4, NativeType::FLOAT64 => 8, NativeType::LONG => FFI::Platform::LONG_SIZE / 8, NativeType::ULONG => FFI::Platform::LONG_SIZE / 8, NativeType::POINTER => FFI::Platform::ADDRESS_SIZE / 8, }) def self.size_to_type(size) if sz = TypeSizes[size] return sz end # Be like C, use int as the default type size. return :int end def self.type_size(type) if sz = SizeTypes[find_type(type)] return sz end raise ArgumentError, "Unknown native type" end # Load all the platform dependent types begin File.open(File.join(FFI::Platform::CONF_DIR, 'types.conf'), "r") do |f| prefix = "rbx.platform.typedef." f.each_line { |line| if line.index(prefix) == 0 new_type, orig_type = line.chomp.slice(prefix.length..-1).split(/\s*=\s*/) add_typedef(orig_type.to_sym, new_type.to_sym) end } end rescue Errno::ENOENT end end