Warning: file_get_contents(https://raw.githubusercontent.com/Den1xxx/Filemanager/master/languages/ru.json): failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 88

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 215

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 216

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 217

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 218

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 219

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 220
PK!cx x value.rbnu[# frozen_string_literal: true require 'fiddle' module Fiddle module ValueUtil #:nodoc: all def unsigned_value(val, ty) case ty.abs when TYPE_CHAR [val].pack("c").unpack("C")[0] when TYPE_SHORT [val].pack("s!").unpack("S!")[0] when TYPE_INT [val].pack("i!").unpack("I!")[0] when TYPE_LONG [val].pack("l!").unpack("L!")[0] else if defined?(TYPE_LONG_LONG) and ty.abs == TYPE_LONG_LONG [val].pack("q").unpack("Q")[0] else val end end end def signed_value(val, ty) case ty.abs when TYPE_CHAR [val].pack("C").unpack("c")[0] when TYPE_SHORT [val].pack("S!").unpack("s!")[0] when TYPE_INT [val].pack("I!").unpack("i!")[0] when TYPE_LONG [val].pack("L!").unpack("l!")[0] else if defined?(TYPE_LONG_LONG) and ty.abs == TYPE_LONG_LONG [val].pack("Q").unpack("q")[0] else val end end end def wrap_args(args, tys, funcs, &block) result = [] tys ||= [] args.each_with_index{|arg, idx| result.push(wrap_arg(arg, tys[idx], funcs, &block)) } result end def wrap_arg(arg, ty, funcs = [], &block) funcs ||= [] case arg when nil return 0 when Pointer return arg.to_i when IO case ty when TYPE_VOIDP return Pointer[arg].to_i else return arg.to_i end when Function if( block ) arg.bind_at_call(&block) funcs.push(arg) elsif !arg.bound? raise(RuntimeError, "block must be given.") end return arg.to_i when String if( ty.is_a?(Array) ) return arg.unpack('C*') else case SIZEOF_VOIDP when SIZEOF_LONG return [arg].pack("p").unpack("l!")[0] else if defined?(SIZEOF_LONG_LONG) and SIZEOF_VOIDP == SIZEOF_LONG_LONG return [arg].pack("p").unpack("q")[0] else raise(RuntimeError, "sizeof(void*)?") end end end when Float, Integer return arg when Array if( ty.is_a?(Array) ) # used only by struct case ty[0] when TYPE_VOIDP return arg.collect{|v| Integer(v)} when TYPE_CHAR if( arg.is_a?(String) ) return val.unpack('C*') end end return arg else return arg end else if( arg.respond_to?(:to_ptr) ) return arg.to_ptr.to_i else begin return Integer(arg) rescue raise(ArgumentError, "unknown argument type: #{arg.class}") end end end end end end PK!]u&& version.rbnu[module Fiddle VERSION = "1.1.1" end PK!_ closure.rbnu[# frozen_string_literal: true module Fiddle class Closure class << self # Create a new closure. If a block is given, the created closure # is automatically freed after the given block is executed. # # The all given arguments are passed to Fiddle::Closure.new. So # using this method without block equals to Fiddle::Closure.new. # # == Example # # Fiddle::Closure.create(TYPE_INT, [TYPE_INT]) do |closure| # # closure is freed automatically when this block is finished. # end def create(*args) if block_given? closure = new(*args) begin yield(closure) ensure closure.free end else new(*args) end end end # the C type of the return of the FFI closure attr_reader :ctype # arguments of the FFI closure attr_reader :args # Extends Fiddle::Closure to allow for building the closure in a block class BlockCaller < Fiddle::Closure # == Description # # Construct a new BlockCaller object. # # * +ctype+ is the C type to be returned # * +args+ are passed the callback # * +abi+ is the abi of the closure # # If there is an error in preparing the +ffi_cif+ or +ffi_prep_closure+, # then a RuntimeError will be raised. # # == Example # # include Fiddle # # cb = Closure::BlockCaller.new(TYPE_INT, [TYPE_INT]) do |one| # one # end # # func = Function.new(cb, [TYPE_INT], TYPE_INT) # def initialize ctype, args, abi = Fiddle::Function::DEFAULT, &block super(ctype, args, abi) @block = block end # Calls the constructed BlockCaller, with +args+ # # For an example see Fiddle::Closure::BlockCaller.new # def call *args @block.call(*args) end end end end PK!types.rbnu[# frozen_string_literal: true module Fiddle # Adds Windows type aliases to the including class for use with # Fiddle::Importer. # # The aliases added are: # * ATOM # * BOOL # * BYTE # * DWORD # * DWORD32 # * DWORD64 # * HANDLE # * HDC # * HINSTANCE # * HWND # * LPCSTR # * LPSTR # * PBYTE # * PDWORD # * PHANDLE # * PVOID # * PWORD # * UCHAR # * UINT # * ULONG # * WORD module Win32Types def included(m) # :nodoc: # https://docs.microsoft.com/en-us/windows/win32/winprog/windows-data-types m.module_eval{ typealias "ATOM", "WORD" typealias "BOOL", "int" typealias "BYTE", "unsigned char" typealias "DWORD", "unsigned long" typealias "DWORD32", "uint32_t" typealias "DWORD64", "uint64_t" typealias "HANDLE", "PVOID" typealias "HDC", "HANDLE" typealias "HINSTANCE", "HANDLE" typealias "HWND", "HANDLE" typealias "LPCSTR", "const char *" typealias "LPSTR", "char *" typealias "PBYTE", "BYTE *" typealias "PDWORD", "DWORD *" typealias "PHANDLE", "HANDLE *" typealias "PVOID", "void *" typealias "PWORD", "WORD *" typealias "UCHAR", "unsigned char" typealias "UINT", "unsigned int" typealias "ULONG", "unsigned long" typealias "WORD", "unsigned short" } end module_function :included end # Adds basic type aliases to the including class for use with Fiddle::Importer. # # The aliases added are +uint+ and +u_int+ (unsigned int) and # +ulong+ and +u_long+ (unsigned long) module BasicTypes def included(m) # :nodoc: m.module_eval{ typealias "uint", "unsigned int" typealias "u_int", "unsigned int" typealias "ulong", "unsigned long" typealias "u_long", "unsigned long" } end module_function :included end end PK!a"a" cparser.rbnu[# frozen_string_literal: true module Fiddle # A mixin that provides methods for parsing C struct and prototype signatures. # # == Example # require 'fiddle/import' # # include Fiddle::CParser # #=> Object # # parse_ctype('int') # #=> Fiddle::TYPE_INT # # parse_struct_signature(['int i', 'char c']) # #=> [[Fiddle::TYPE_INT, Fiddle::TYPE_CHAR], ["i", "c"]] # # parse_signature('double sum(double, double)') # #=> ["sum", Fiddle::TYPE_DOUBLE, [Fiddle::TYPE_DOUBLE, Fiddle::TYPE_DOUBLE]] # module CParser # Parses a C struct's members # # Example: # require 'fiddle/import' # # include Fiddle::CParser # #=> Object # # parse_struct_signature(['int i', 'char c']) # #=> [[Fiddle::TYPE_INT, Fiddle::TYPE_CHAR], ["i", "c"]] # # parse_struct_signature(['char buffer[80]']) # #=> [[[Fiddle::TYPE_CHAR, 80]], ["buffer"]] # def parse_struct_signature(signature, tymap=nil) if signature.is_a?(String) signature = split_arguments(signature, /[,;]/) elsif signature.is_a?(Hash) signature = [signature] end mems = [] tys = [] signature.each{|msig| msig = compact(msig) if msig.is_a?(String) case msig when Hash msig.each do |struct_name, struct_signature| struct_name = struct_name.to_s if struct_name.is_a?(Symbol) struct_name = compact(struct_name) struct_count = nil if struct_name =~ /^([\w\*\s]+)\[(\d+)\]$/ struct_count = $2.to_i struct_name = $1 end if struct_signature.respond_to?(:entity_class) struct_type = struct_signature else parsed_struct = parse_struct_signature(struct_signature, tymap) struct_type = CStructBuilder.create(CStruct, *parsed_struct) end if struct_count ty = [struct_type, struct_count] else ty = struct_type end mems.push([struct_name, struct_type.members]) tys.push(ty) end when /^[\w\*\s]+[\*\s](\w+)$/ mems.push($1) tys.push(parse_ctype(msig, tymap)) when /^[\w\*\s]+\(\*(\w+)\)\(.*?\)$/ mems.push($1) tys.push(parse_ctype(msig, tymap)) when /^([\w\*\s]+[\*\s])(\w+)\[(\d+)\]$/ mems.push($2) tys.push([parse_ctype($1.strip, tymap), $3.to_i]) when /^([\w\*\s]+)\[(\d+)\](\w+)$/ mems.push($3) tys.push([parse_ctype($1.strip, tymap), $2.to_i]) else raise(RuntimeError,"can't parse the struct member: #{msig}") end } return tys, mems end # Parses a C prototype signature # # If Hash +tymap+ is provided, the return value and the arguments from the # +signature+ are expected to be keys, and the value will be the C type to # be looked up. # # Example: # require 'fiddle/import' # # include Fiddle::CParser # #=> Object # # parse_signature('double sum(double, double)') # #=> ["sum", Fiddle::TYPE_DOUBLE, [Fiddle::TYPE_DOUBLE, Fiddle::TYPE_DOUBLE]] # # parse_signature('void update(void (*cb)(int code))') # #=> ["update", Fiddle::TYPE_VOID, [Fiddle::TYPE_VOIDP]] # # parse_signature('char (*getbuffer(void))[80]') # #=> ["getbuffer", Fiddle::TYPE_VOIDP, []] # def parse_signature(signature, tymap=nil) tymap ||= {} case compact(signature) when /^(?:[\w\*\s]+)\(\*(\w+)\((.*?)\)\)(?:\[\w*\]|\(.*?\));?$/ func, args = $1, $2 return [func, TYPE_VOIDP, split_arguments(args).collect {|arg| parse_ctype(arg, tymap)}] when /^([\w\*\s]+[\*\s])(\w+)\((.*?)\);?$/ ret, func, args = $1.strip, $2, $3 return [func, parse_ctype(ret, tymap), split_arguments(args).collect {|arg| parse_ctype(arg, tymap)}] else raise(RuntimeError,"can't parse the function prototype: #{signature}") end end # Given a String of C type +ty+, returns the corresponding Fiddle constant. # # +ty+ can also accept an Array of C type Strings, and will be returned in # a corresponding Array. # # If Hash +tymap+ is provided, +ty+ is expected to be the key, and the # value will be the C type to be looked up. # # Example: # require 'fiddle/import' # # include Fiddle::CParser # #=> Object # # parse_ctype('int') # #=> Fiddle::TYPE_INT # # parse_ctype('double diff') # #=> Fiddle::TYPE_DOUBLE # # parse_ctype('unsigned char byte') # #=> -Fiddle::TYPE_CHAR # # parse_ctype('const char* const argv[]') # #=> -Fiddle::TYPE_VOIDP # def parse_ctype(ty, tymap=nil) tymap ||= {} if ty.is_a?(Array) return [parse_ctype(ty[0], tymap), ty[1]] end ty = ty.gsub(/\Aconst\s+/, "") case ty when 'void' return TYPE_VOID when /\A(?:(?:signed\s+)?long\s+long(?:\s+int\s+)?|int64_t)(?:\s+\w+)?\z/ unless Fiddle.const_defined?(:TYPE_LONG_LONG) raise(RuntimeError, "unsupported type: #{ty}") end return TYPE_LONG_LONG when /\A(?:unsigned\s+long\s+long(?:\s+int\s+)?|uint64_t)(?:\s+\w+)?\z/ unless Fiddle.const_defined?(:TYPE_LONG_LONG) raise(RuntimeError, "unsupported type: #{ty}") end return TYPE_ULONG_LONG when /\A(?:signed\s+)?long(?:\s+int\s+)?(?:\s+\w+)?\z/ return TYPE_LONG when /\Aunsigned\s+long(?:\s+int\s+)?(?:\s+\w+)?\z/ return TYPE_ULONG when /\A(?:signed\s+)?int(?:\s+\w+)?\z/ return TYPE_INT when /\A(?:unsigned\s+int|uint)(?:\s+\w+)?\z/ return TYPE_UINT when /\A(?:signed\s+)?short(?:\s+int\s+)?(?:\s+\w+)?\z/ return TYPE_SHORT when /\Aunsigned\s+short(?:\s+int\s+)?(?:\s+\w+)?\z/ return TYPE_USHORT when /\A(?:signed\s+)?char(?:\s+\w+)?\z/ return TYPE_CHAR when /\Aunsigned\s+char(?:\s+\w+)?\z/ return TYPE_UCHAR when /\Aint8_t(?:\s+\w+)?\z/ unless Fiddle.const_defined?(:TYPE_INT8_T) raise(RuntimeError, "unsupported type: #{ty}") end return TYPE_INT8_T when /\Auint8_t(?:\s+\w+)?\z/ unless Fiddle.const_defined?(:TYPE_INT8_T) raise(RuntimeError, "unsupported type: #{ty}") end return TYPE_UINT8_T when /\Aint16_t(?:\s+\w+)?\z/ unless Fiddle.const_defined?(:TYPE_INT16_T) raise(RuntimeError, "unsupported type: #{ty}") end return TYPE_INT16_T when /\Auint16_t(?:\s+\w+)?\z/ unless Fiddle.const_defined?(:TYPE_INT16_T) raise(RuntimeError, "unsupported type: #{ty}") end return TYPE_UINT16_T when /\Aint32_t(?:\s+\w+)?\z/ unless Fiddle.const_defined?(:TYPE_INT32_T) raise(RuntimeError, "unsupported type: #{ty}") end return TYPE_INT32_T when /\Auint32_t(?:\s+\w+)?\z/ unless Fiddle.const_defined?(:TYPE_INT32_T) raise(RuntimeError, "unsupported type: #{ty}") end return TYPE_UINT32_T when /\Aint64_t(?:\s+\w+)?\z/ unless Fiddle.const_defined?(:TYPE_INT64_T) raise(RuntimeError, "unsupported type: #{ty}") end return TYPE_INT64_T when /\Auint64_t(?:\s+\w+)?\z/ unless Fiddle.const_defined?(:TYPE_INT64_T) raise(RuntimeError, "unsupported type: #{ty}") end return TYPE_UINT64_T when /\Afloat(?:\s+\w+)?\z/ return TYPE_FLOAT when /\Adouble(?:\s+\w+)?\z/ return TYPE_DOUBLE when /\Asize_t(?:\s+\w+)?\z/ return TYPE_SIZE_T when /\Assize_t(?:\s+\w+)?\z/ return TYPE_SSIZE_T when /\Aptrdiff_t(?:\s+\w+)?\z/ return TYPE_PTRDIFF_T when /\Aintptr_t(?:\s+\w+)?\z/ return TYPE_INTPTR_T when /\Auintptr_t(?:\s+\w+)?\z/ return TYPE_UINTPTR_T when /\*/, /\[[\s\d]*\]/ return TYPE_VOIDP when "..." return TYPE_VARIADIC else ty = ty.split(' ', 2)[0] if( tymap[ty] ) return parse_ctype(tymap[ty], tymap) else raise(DLError, "unknown type: #{ty}") end end end private def split_arguments(arguments, sep=',') return [] if arguments.strip == 'void' arguments.scan(/([\w\*\s]+\(\*\w*\)\(.*?\)|[\w\*\s\[\]]+|\.\.\.)(?:#{sep}\s*|\z)/).collect {|m| m[0]} end def compact(signature) signature.gsub(/\s+/, ' ').gsub(/\s*([\(\)\[\]\*,;])\s*/, '\1').strip end end end PK!ߓ## import.rbnu[# frozen_string_literal: true require 'fiddle' require 'fiddle/struct' require 'fiddle/cparser' module Fiddle # Used internally by Fiddle::Importer class CompositeHandler # Create a new handler with the open +handlers+ # # Used internally by Fiddle::Importer.dlload def initialize(handlers) @handlers = handlers end # Array of the currently loaded libraries. def handlers() @handlers end # Returns the address as an Integer from any handlers with the function # named +symbol+. # # Raises a DLError if the handle is closed. def sym(symbol) @handlers.each{|handle| if( handle ) begin addr = handle.sym(symbol) return addr rescue DLError end end } return nil end # See Fiddle::CompositeHandler.sym def [](symbol) sym(symbol) end end # A DSL that provides the means to dynamically load libraries and build # modules around them including calling extern functions within the C # library that has been loaded. # # == Example # # require 'fiddle' # require 'fiddle/import' # # module LibSum # extend Fiddle::Importer # dlload './libsum.so' # extern 'double sum(double*, int)' # extern 'double split(double)' # end # module Importer include Fiddle include CParser extend Importer attr_reader :type_alias private :type_alias # Creates an array of handlers for the given +libs+, can be an instance of # Fiddle::Handle, Fiddle::Importer, or will create a new instance of # Fiddle::Handle using Fiddle.dlopen # # Raises a DLError if the library cannot be loaded. # # See Fiddle.dlopen def dlload(*libs) handles = libs.collect{|lib| case lib when nil nil when Handle lib when Importer lib.handlers else Fiddle.dlopen(lib) end }.flatten() @handler = CompositeHandler.new(handles) @func_map = {} @type_alias = {} end # Sets the type alias for +alias_type+ as +orig_type+ def typealias(alias_type, orig_type) @type_alias[alias_type] = orig_type end # Returns the sizeof +ty+, using Fiddle::Importer.parse_ctype to determine # the C type and the appropriate Fiddle constant. def sizeof(ty) case ty when String ty = parse_ctype(ty, type_alias).abs() case ty when TYPE_CHAR return SIZEOF_CHAR when TYPE_SHORT return SIZEOF_SHORT when TYPE_INT return SIZEOF_INT when TYPE_LONG return SIZEOF_LONG when TYPE_FLOAT return SIZEOF_FLOAT when TYPE_DOUBLE return SIZEOF_DOUBLE when TYPE_VOIDP return SIZEOF_VOIDP when TYPE_CONST_STRING return SIZEOF_CONST_STRING else if defined?(TYPE_LONG_LONG) and ty == TYPE_LONG_LONG return SIZEOF_LONG_LONG else raise(DLError, "unknown type: #{ty}") end end when Class if( ty.instance_methods().include?(:to_ptr) ) return ty.size() end end return Pointer[ty].size() end def parse_bind_options(opts) h = {} while( opt = opts.shift() ) case opt when :stdcall, :cdecl h[:call_type] = opt when :carried, :temp, :temporal, :bind h[:callback_type] = opt h[:carrier] = opts.shift() else h[opt] = true end end h end private :parse_bind_options # :stopdoc: CALL_TYPE_TO_ABI = Hash.new { |h, k| raise RuntimeError, "unsupported call type: #{k}" }.merge({ :stdcall => Function.const_defined?(:STDCALL) ? Function::STDCALL : Function::DEFAULT, :cdecl => Function::DEFAULT, nil => Function::DEFAULT }).freeze private_constant :CALL_TYPE_TO_ABI # :startdoc: # Creates a global method from the given C +signature+. def extern(signature, *opts) symname, ctype, argtype = parse_signature(signature, type_alias) opt = parse_bind_options(opts) f = import_function(symname, ctype, argtype, opt[:call_type]) name = symname.gsub(/@.+/,'') @func_map[name] = f # define_method(name){|*args,&block| f.call(*args,&block)} begin /^(.+?):(\d+)/ =~ caller.first file, line = $1, $2.to_i rescue file, line = __FILE__, __LINE__+3 end module_eval(<<-EOS, file, line) def #{name}(*args, &block) @func_map['#{name}'].call(*args,&block) end EOS module_function(name) f end # Creates a global method from the given C +signature+ using the given # +opts+ as bind parameters with the given block. def bind(signature, *opts, &blk) name, ctype, argtype = parse_signature(signature, type_alias) h = parse_bind_options(opts) case h[:callback_type] when :bind, nil f = bind_function(name, ctype, argtype, h[:call_type], &blk) else raise(RuntimeError, "unknown callback type: #{h[:callback_type]}") end @func_map[name] = f #define_method(name){|*args,&block| f.call(*args,&block)} begin /^(.+?):(\d+)/ =~ caller.first file, line = $1, $2.to_i rescue file, line = __FILE__, __LINE__+3 end module_eval(<<-EOS, file, line) def #{name}(*args,&block) @func_map['#{name}'].call(*args,&block) end EOS module_function(name) f end # Creates a class to wrap the C struct described by +signature+. # # MyStruct = struct ['int i', 'char c'] def struct(signature) tys, mems = parse_struct_signature(signature, type_alias) Fiddle::CStructBuilder.create(CStruct, tys, mems) end # Creates a class to wrap the C union described by +signature+. # # MyUnion = union ['int i', 'char c'] def union(signature) tys, mems = parse_struct_signature(signature, type_alias) Fiddle::CStructBuilder.create(CUnion, tys, mems) end # Returns the function mapped to +name+, that was created by either # Fiddle::Importer.extern or Fiddle::Importer.bind def [](name) @func_map[name] end # Creates a class to wrap the C struct with the value +ty+ # # See also Fiddle::Importer.struct def create_value(ty, val=nil) s = struct([ty + " value"]) ptr = s.malloc() if( val ) ptr.value = val end return ptr end alias value create_value # Returns a new instance of the C struct with the value +ty+ at the +addr+ # address. def import_value(ty, addr) s = struct([ty + " value"]) ptr = s.new(addr) return ptr end # The Fiddle::CompositeHandler instance # # Will raise an error if no handlers are open. def handler (@handler ||= nil) or raise "call dlload before importing symbols and functions" end # Returns a new Fiddle::Pointer instance at the memory address of the given # +name+ symbol. # # Raises a DLError if the +name+ doesn't exist. # # See Fiddle::CompositeHandler.sym and Fiddle::Handle.sym def import_symbol(name) addr = handler.sym(name) if( !addr ) raise(DLError, "cannot find the symbol: #{name}") end Pointer.new(addr) end # Returns a new Fiddle::Function instance at the memory address of the given # +name+ function. # # Raises a DLError if the +name+ doesn't exist. # # * +argtype+ is an Array of arguments, passed to the +name+ function. # * +ctype+ is the return type of the function # * +call_type+ is the ABI of the function # # See also Fiddle:Function.new # # See Fiddle::CompositeHandler.sym and Fiddle::Handler.sym def import_function(name, ctype, argtype, call_type = nil) addr = handler.sym(name) if( !addr ) raise(DLError, "cannot find the function: #{name}()") end Function.new(addr, argtype, ctype, CALL_TYPE_TO_ABI[call_type], name: name) end # Returns a new closure wrapper for the +name+ function. # # * +ctype+ is the return type of the function # * +argtype+ is an Array of arguments, passed to the callback function # * +call_type+ is the abi of the closure # * +block+ is passed to the callback # # See Fiddle::Closure def bind_function(name, ctype, argtype, call_type = nil, &block) abi = CALL_TYPE_TO_ABI[call_type] closure = Class.new(Fiddle::Closure) { define_method(:call, block) }.new(ctype, argtype, abi) Function.new(closure, argtype, ctype, abi, name: name) end end end PK!w function.rbnu[# frozen_string_literal: true module Fiddle class Function # The ABI of the Function. attr_reader :abi # The address of this function attr_reader :ptr # The name of this function attr_reader :name # Whether GVL is needed to call this function def need_gvl? @need_gvl end # The integer memory location of this function def to_i ptr.to_i end # Turn this function in to a proc def to_proc this = self lambda { |*args| this.call(*args) } end end end PK!aD4 pack.rbnu[# frozen_string_literal: true require 'fiddle' module Fiddle module PackInfo # :nodoc: all ALIGN_MAP = { TYPE_VOIDP => ALIGN_VOIDP, TYPE_CHAR => ALIGN_CHAR, TYPE_SHORT => ALIGN_SHORT, TYPE_INT => ALIGN_INT, TYPE_LONG => ALIGN_LONG, TYPE_FLOAT => ALIGN_FLOAT, TYPE_DOUBLE => ALIGN_DOUBLE, TYPE_UCHAR => ALIGN_CHAR, TYPE_USHORT => ALIGN_SHORT, TYPE_UINT => ALIGN_INT, TYPE_ULONG => ALIGN_LONG, } PACK_MAP = { TYPE_VOIDP => "L!", TYPE_CHAR => "c", TYPE_SHORT => "s!", TYPE_INT => "i!", TYPE_LONG => "l!", TYPE_FLOAT => "f", TYPE_DOUBLE => "d", TYPE_UCHAR => "C", TYPE_USHORT => "S!", TYPE_UINT => "I!", TYPE_ULONG => "L!", } SIZE_MAP = { TYPE_VOIDP => SIZEOF_VOIDP, TYPE_CHAR => SIZEOF_CHAR, TYPE_SHORT => SIZEOF_SHORT, TYPE_INT => SIZEOF_INT, TYPE_LONG => SIZEOF_LONG, TYPE_FLOAT => SIZEOF_FLOAT, TYPE_DOUBLE => SIZEOF_DOUBLE, TYPE_UCHAR => SIZEOF_CHAR, TYPE_USHORT => SIZEOF_SHORT, TYPE_UINT => SIZEOF_INT, TYPE_ULONG => SIZEOF_LONG, } if defined?(TYPE_LONG_LONG) ALIGN_MAP[TYPE_LONG_LONG] = ALIGN_MAP[TYPE_ULONG_LONG] = ALIGN_LONG_LONG PACK_MAP[TYPE_LONG_LONG] = "q" PACK_MAP[TYPE_ULONG_LONG] = "Q" SIZE_MAP[TYPE_LONG_LONG] = SIZE_MAP[TYPE_ULONG_LONG] = SIZEOF_LONG_LONG PACK_MAP[TYPE_VOIDP] = "Q" if SIZEOF_LONG_LONG == SIZEOF_VOIDP end def align(addr, align) d = addr % align if( d == 0 ) addr else addr + (align - d) end end module_function :align end class Packer # :nodoc: all include PackInfo def self.[](*types) new(types) end def initialize(types) parse_types(types) end def size() @size end def pack(ary) case SIZEOF_VOIDP when SIZEOF_LONG ary.pack(@template) else if defined?(TYPE_LONG_LONG) and SIZEOF_VOIDP == SIZEOF_LONG_LONG ary.pack(@template) else raise(RuntimeError, "sizeof(void*)?") end end end def unpack(ary) case SIZEOF_VOIDP when SIZEOF_LONG ary.join().unpack(@template) else if defined?(TYPE_LONG_LONG) and SIZEOF_VOIDP == SIZEOF_LONG_LONG ary.join().unpack(@template) else raise(RuntimeError, "sizeof(void*)?") end end end private def parse_types(types) @template = "".dup addr = 0 types.each{|t| orig_addr = addr if( t.is_a?(Array) ) addr = align(orig_addr, ALIGN_MAP[TYPE_VOIDP]) else addr = align(orig_addr, ALIGN_MAP[t]) end d = addr - orig_addr if( d > 0 ) @template << "x#{d}" end if( t.is_a?(Array) ) @template << (PACK_MAP[t[0]] * t[1]) addr += (SIZE_MAP[t[0]] * t[1]) else @template << PACK_MAP[t] addr += SIZE_MAP[t] end } addr = align(addr, ALIGN_MAP[TYPE_VOIDP]) @size = addr end end end PK!\88 struct.rbnu[# frozen_string_literal: true require 'fiddle' require 'fiddle/value' require 'fiddle/pack' module Fiddle # A base class for objects representing a C structure class CStruct include Enumerable # accessor to Fiddle::CStructEntity def CStruct.entity_class CStructEntity end def self.offsetof(name, members, types) # :nodoc: offset = 0 worklist = name.split('.') this_type = self while search_name = worklist.shift index = 0 member_index = members.index(search_name) unless member_index # Possibly a sub-structure member_index = members.index { |member_name, _| member_name == search_name } return unless member_index end types.each { |type, count = 1| orig_offset = offset if type.respond_to?(:entity_class) align = type.alignment type_size = type.size else align = PackInfo::ALIGN_MAP[type] type_size = PackInfo::SIZE_MAP[type] end # Unions shouldn't advance the offset if this_type.entity_class == CUnionEntity type_size = 0 end offset = PackInfo.align(orig_offset, align) if worklist.empty? return offset if index == member_index else if index == member_index subtype = types[member_index] members = subtype.members types = subtype.types this_type = subtype break end end offset += (type_size * count) index += 1 } end nil end def each return enum_for(__function__) unless block_given? self.class.members.each do |name,| yield(self[name]) end end def each_pair return enum_for(__function__) unless block_given? self.class.members.each do |name,| yield(name, self[name]) end end def to_h hash = {} each_pair do |name, value| hash[name] = unstruct(value) end hash end def replace(another) if another.nil? self.class.members.each do |name,| self[name] = nil end elsif another.respond_to?(:each_pair) another.each_pair do |name, value| self[name] = value end else another.each do |name, value| self[name] = value end end self end private def unstruct(value) case value when CStruct value.to_h when Array value.collect do |v| unstruct(v) end else value end end end # A base class for objects representing a C union class CUnion # accessor to Fiddle::CUnionEntity def CUnion.entity_class CUnionEntity end def self.offsetof(name, members, types) # :nodoc: 0 end end # Wrapper for arrays within a struct class StructArray < Array include ValueUtil def initialize(ptr, type, initial_values) @ptr = ptr @type = type @is_struct = @type.respond_to?(:entity_class) if @is_struct super(initial_values) else @size = Fiddle::PackInfo::SIZE_MAP[type] @pack_format = Fiddle::PackInfo::PACK_MAP[type] super(initial_values.collect { |v| unsigned_value(v, type) }) end end def to_ptr @ptr end def []=(index, value) if index < 0 || index >= size raise IndexError, 'index %d outside of array bounds 0...%d' % [index, size] end if @is_struct self[index].replace(value) else to_ptr[index * @size, @size] = [value].pack(@pack_format) super(index, value) end end end # Used to construct C classes (CUnion, CStruct, etc) # # Fiddle::Importer#struct and Fiddle::Importer#union wrap this functionality in an # easy-to-use manner. module CStructBuilder # Construct a new class given a C: # * class +klass+ (CUnion, CStruct, or other that provide an # #entity_class) # * +types+ (Fiddle::TYPE_INT, Fiddle::TYPE_SIZE_T, etc., see the C types # constants) # * corresponding +members+ # # Fiddle::Importer#struct and Fiddle::Importer#union wrap this functionality in an # easy-to-use manner. # # Examples: # # require 'fiddle/struct' # require 'fiddle/cparser' # # include Fiddle::CParser # # types, members = parse_struct_signature(['int i','char c']) # # MyStruct = Fiddle::CStructBuilder.create(Fiddle::CUnion, types, members) # # MyStruct.malloc(Fiddle::RUBY_FREE) do |obj| # ... # end # # obj = MyStruct.malloc(Fiddle::RUBY_FREE) # begin # ... # ensure # obj.call_free # end # # obj = MyStruct.malloc # begin # ... # ensure # Fiddle.free obj.to_ptr # end # def create(klass, types, members) new_class = Class.new(klass){ define_method(:initialize){|addr, func = nil| if addr.is_a?(self.class.entity_class) @entity = addr else @entity = self.class.entity_class.new(addr, types, func) end @entity.assign_names(members) } define_method(:[]) { |*args| @entity.send(:[], *args) } define_method(:[]=) { |*args| @entity.send(:[]=, *args) } define_method(:to_ptr){ @entity } define_method(:to_i){ @entity.to_i } define_singleton_method(:types) { types } define_singleton_method(:members) { members } # Return the offset of a struct member given its name. # For example: # # MyStruct = struct [ # "int64_t i", # "char c", # ] # # MyStruct.offsetof("i") # => 0 # MyStruct.offsetof("c") # => 8 # define_singleton_method(:offsetof) { |name| klass.offsetof(name, members, types) } members.each{|name| name = name[0] if name.is_a?(Array) # name is a nested struct next if method_defined?(name) define_method(name){ @entity[name] } define_method(name + "="){|val| @entity[name] = val } } entity_class = klass.entity_class alignment = entity_class.alignment(types) size = entity_class.size(types) define_singleton_method(:alignment) { alignment } define_singleton_method(:size) { size } define_singleton_method(:malloc) do |func=nil, &block| if block entity_class.malloc(types, func, size) do |entity| block.call(new(entity)) end else new(entity_class.malloc(types, func, size)) end end } return new_class end module_function :create end # A pointer to a C structure class CStructEntity < Fiddle::Pointer include PackInfo include ValueUtil def CStructEntity.alignment(types) max = 1 types.each do |type, count = 1| if type.respond_to?(:entity_class) n = type.alignment else n = ALIGN_MAP[type] end max = n if n > max end max end # Allocates a C struct with the +types+ provided. # # See Fiddle::Pointer.malloc for memory management issues. def CStructEntity.malloc(types, func = nil, size = size(types), &block) if block_given? super(size, func) do |struct| struct.set_ctypes types yield struct end else struct = super(size, func) struct.set_ctypes types struct end end # Returns the offset for the packed sizes for the given +types+. # # Fiddle::CStructEntity.size( # [ Fiddle::TYPE_DOUBLE, # Fiddle::TYPE_INT, # Fiddle::TYPE_CHAR, # Fiddle::TYPE_VOIDP ]) #=> 24 def CStructEntity.size(types) offset = 0 max_align = types.map { |type, count = 1| last_offset = offset if type.respond_to?(:entity_class) align = type.alignment type_size = type.size else align = PackInfo::ALIGN_MAP[type] type_size = PackInfo::SIZE_MAP[type] end offset = PackInfo.align(last_offset, align) + (type_size * count) align }.max PackInfo.align(offset, max_align) end # Wraps the C pointer +addr+ as a C struct with the given +types+. # # When the instance is garbage collected, the C function +func+ is called. # # See also Fiddle::Pointer.new def initialize(addr, types, func = nil) if func && addr.is_a?(Pointer) && addr.free raise ArgumentError, 'free function specified on both underlying struct Pointer and when creating a CStructEntity - who do you want to free this?' end set_ctypes(types) super(addr, @size, func) end # Set the names of the +members+ in this C struct def assign_names(members) @members = [] @nested_structs = {} members.each_with_index do |member, index| if member.is_a?(Array) # nested struct member_name = member[0] struct_type, struct_count = @ctypes[index] if struct_count.nil? struct = struct_type.new(to_i + @offset[index]) else structs = struct_count.times.map do |i| struct_type.new(to_i + @offset[index] + i * struct_type.size) end struct = StructArray.new(to_i + @offset[index], struct_type, structs) end @nested_structs[member_name] = struct else member_name = member end @members << member_name end end # Calculates the offsets and sizes for the given +types+ in the struct. def set_ctypes(types) @ctypes = types @offset = [] offset = 0 max_align = types.map { |type, count = 1| orig_offset = offset if type.respond_to?(:entity_class) align = type.alignment type_size = type.size else align = ALIGN_MAP[type] type_size = SIZE_MAP[type] end offset = PackInfo.align(orig_offset, align) @offset << offset offset += (type_size * count) align }.max @size = PackInfo.align(offset, max_align) end # Fetch struct member +name+ if only one argument is specified. If two # arguments are specified, the first is an offset and the second is a # length and this method returns the string of +length+ bytes beginning at # +offset+. # # Examples: # # my_struct = struct(['int id']).malloc # my_struct.id = 1 # my_struct['id'] # => 1 # my_struct[0, 4] # => "\x01\x00\x00\x00".b # def [](*args) return super(*args) if args.size > 1 name = args[0] idx = @members.index(name) if( idx.nil? ) raise(ArgumentError, "no such member: #{name}") end ty = @ctypes[idx] if( ty.is_a?(Array) ) if ty.first.respond_to?(:entity_class) return @nested_structs[name] else r = super(@offset[idx], SIZE_MAP[ty[0]] * ty[1]) end elsif ty.respond_to?(:entity_class) return @nested_structs[name] else r = super(@offset[idx], SIZE_MAP[ty.abs]) end packer = Packer.new([ty]) val = packer.unpack([r]) case ty when Array case ty[0] when TYPE_VOIDP val = val.collect{|v| Pointer.new(v)} end when TYPE_VOIDP val = Pointer.new(val[0]) else val = val[0] end if( ty.is_a?(Integer) && (ty < 0) ) return unsigned_value(val, ty) elsif( ty.is_a?(Array) && (ty[0] < 0) ) return StructArray.new(self + @offset[idx], ty[0], val) else return val end end # Set struct member +name+, to value +val+. If more arguments are # specified, writes the string of bytes to the memory at the given # +offset+ and +length+. # # Examples: # # my_struct = struct(['int id']).malloc # my_struct['id'] = 1 # my_struct[0, 4] = "\x01\x00\x00\x00".b # my_struct.id # => 1 # def []=(*args) return super(*args) if args.size > 2 name, val = *args name = name.to_s if name.is_a?(Symbol) nested_struct = @nested_structs[name] if nested_struct if nested_struct.is_a?(StructArray) if val.nil? nested_struct.each do |s| s.replace(nil) end else val.each_with_index do |v, i| nested_struct[i] = v end end else nested_struct.replace(val) end return val end idx = @members.index(name) if( idx.nil? ) raise(ArgumentError, "no such member: #{name}") end ty = @ctypes[idx] packer = Packer.new([ty]) val = wrap_arg(val, ty, []) buff = packer.pack([val].flatten()) super(@offset[idx], buff.size, buff) if( ty.is_a?(Integer) && (ty < 0) ) return unsigned_value(val, ty) elsif( ty.is_a?(Array) && (ty[0] < 0) ) return val.collect{|v| unsigned_value(v,ty[0])} else return val end end undef_method :size= def to_s() # :nodoc: super(@size) end end # A pointer to a C union class CUnionEntity < CStructEntity include PackInfo # Returns the size needed for the union with the given +types+. # # Fiddle::CUnionEntity.size( # [ Fiddle::TYPE_DOUBLE, # Fiddle::TYPE_INT, # Fiddle::TYPE_CHAR, # Fiddle::TYPE_VOIDP ]) #=> 8 def CUnionEntity.size(types) types.map { |type, count = 1| if type.respond_to?(:entity_class) type.size * count else PackInfo::SIZE_MAP[type] * count end }.max end # Calculate the necessary offset and for each union member with the given # +types+ def set_ctypes(types) @ctypes = types @offset = Array.new(types.length, 0) @size = self.class.size types end end end PK!cx x value.rbnu[PK!]u&&  version.rbnu[PK!_  closure.rbnu[PK!types.rbnu[PK!a"a" cparser.rbnu[PK!ߓ## m>import.rbnu[PK!w afunction.rbnu[PK!aD4 dpack.rbnu[PK!\88 pstruct.rbnu[PK