vigilem-support 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/lib/vigilem/ffi.rb +19 -0
  3. data/lib/vigilem/ffi/array_pointer_sync.rb +382 -0
  4. data/lib/vigilem/ffi/struct.rb +54 -0
  5. data/lib/vigilem/ffi/utils.rb +240 -0
  6. data/lib/vigilem/ffi/utils/struct.rb +93 -0
  7. data/lib/vigilem/support.rb +31 -0
  8. data/lib/vigilem/support/core_ext.rb +13 -0
  9. data/lib/vigilem/support/core_ext/debug_puts.rb +5 -0
  10. data/lib/vigilem/support/core_ext/enumerable.rb +25 -0
  11. data/lib/vigilem/support/key_map.rb +323 -0
  12. data/lib/vigilem/support/key_map_info.rb +85 -0
  13. data/lib/vigilem/support/lazy_simple_delegator.rb +81 -0
  14. data/lib/vigilem/support/max_size_error.rb +17 -0
  15. data/lib/vigilem/support/metadata.rb +13 -0
  16. data/lib/vigilem/support/obj_space.rb +28 -0
  17. data/lib/vigilem/support/patch/cucumber/c_lexer.rb +30 -0
  18. data/lib/vigilem/support/patch/ffi/pointer.rb +19 -0
  19. data/lib/vigilem/support/size_error.rb +6 -0
  20. data/lib/vigilem/support/sys.rb +5 -0
  21. data/lib/vigilem/support/system.rb +92 -0
  22. data/lib/vigilem/support/transmutable_hash.rb +206 -0
  23. data/lib/vigilem/support/utils.rb +224 -0
  24. data/lib/vigilem/support/version.rb +5 -0
  25. data/spec/spec_helper.rb +9 -0
  26. data/spec/vigilem/ffi/array_pointer_sync_spec.rb +728 -0
  27. data/spec/vigilem/ffi/struct_spec.rb +22 -0
  28. data/spec/vigilem/ffi/utils/struct_spec.rb +79 -0
  29. data/spec/vigilem/ffi/utils_spec.rb +240 -0
  30. data/spec/vigilem/support/core_ext/enumerable_spec.rb +38 -0
  31. data/spec/vigilem/support/data/cached.kmap +130 -0
  32. data/spec/vigilem/support/data/cached_UTF-8_del.kmap +142 -0
  33. data/spec/vigilem/support/data/cached_short.kmap +38 -0
  34. data/spec/vigilem/support/data/dump_keys_short.kmap +128 -0
  35. data/spec/vigilem/support/key_map_spec.rb +767 -0
  36. data/spec/vigilem/support/lazy_simple_delegator_spec.rb +77 -0
  37. data/spec/vigilem/support/obj_space_spec.rb +47 -0
  38. data/spec/vigilem/support/sys_spec.rb +21 -0
  39. data/spec/vigilem/support/system_spec.rb +31 -0
  40. data/spec/vigilem/support/transmutable_hash_spec.rb +175 -0
  41. data/spec/vigilem/support/utils_spec.rb +214 -0
  42. metadata +240 -0
@@ -0,0 +1,85 @@
1
+ module Vigilem
2
+ module Support
3
+ #
4
+ #
5
+ class KeyMapInfo
6
+
7
+ #
8
+ # @param [Hash] opts
9
+ def initialize(attrs={})
10
+ attrs.each {|attr| send(:"#{attr}=", opts[attr]) }
11
+ end
12
+
13
+ #
14
+ # @return [Array<Symbol>]
15
+ def self.attrs
16
+ @attrs ||= [:keycode_range, :max_actions,
17
+ :number_of_functions_keys, :keymaps_in_use,
18
+ :max_compose_defs, :compose_defs,
19
+ :compose_defs_in_use, :mod_weights, :keysyms]
20
+ end
21
+
22
+ attr_accessor *attrs
23
+
24
+ #
25
+ # @param [String] str
26
+ # @return [KeyMapInfo]
27
+ def self.load_string(str)
28
+ (kmi = new).load_string(str)
29
+ kmi
30
+ end
31
+
32
+ #
33
+ # @param [String] str
34
+ # @return
35
+ def load_string(str)
36
+ str.lines do |substr|
37
+ case substr
38
+ when /^keycode range supported by kernel:/
39
+ keycode_range = substr.split(/:\s+/).last.rstrip
40
+ when /^max number of actions bindable to a key:/
41
+ max_actions = substr.split(/:\s+/).last.rstrip
42
+ when /^number of keymaps in actual use:/
43
+ keymaps_in_use = substr.split(/:\s+/).last.rstrip
44
+ when /^number of function keys supported by kernel:/
45
+ number_of_function_keys = substr.split(/:\s+/).last.rstrip
46
+ when /^max nr of compose definitions:/
47
+ max_compose_defs = substr.split(/:\s+/).last.rstrip
48
+ when /^nr of compose definitions in actual use:/
49
+ compose_defs_in_use = substr.split(/:\s+/).last.rstrip
50
+ when /^0x0[\dA-z]+/
51
+ hex_str, sym = substr.split(/\s+/)
52
+ keysyms[hex_str] = sym.rstrip
53
+ when /[a-z_]\s+for/i
54
+ # synonyms
55
+ when /^(shift|alt|control|ctrl|capsshift)(l|r|gr)?/
56
+ mod, col = substr.split(/\s+/)
57
+ mod_weights[mod] = col.rstrip.to_i
58
+ end
59
+ end
60
+ end
61
+
62
+ #
63
+ # @return [Hash]
64
+ def keysyms
65
+ @keysyms ||= {}
66
+ end
67
+
68
+
69
+ #
70
+ # @return [Hash]
71
+ def char_refs
72
+ keysyms.invert
73
+ end
74
+
75
+ #
76
+ # @return [Hash]
77
+ def mod_weights
78
+ @mod_weights ||= {}
79
+ end
80
+
81
+ alias_method :mod_columns, :mod_weights
82
+
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,81 @@
1
+ require 'delegate'
2
+
3
+ module Vigilem
4
+ module Support
5
+ #
6
+ # a Delegator that allows it's delegate to be named later (after init)
7
+ class LazySimpleDelegator < Delegator
8
+
9
+ methods_to_include = [:to_s, :inspect, :==, :===, :<=>, :eql?, :object_id]
10
+
11
+ (kd = ::Kernel.dup).class_eval do
12
+ ((private_instance_methods | instance_methods) - methods_to_include).each do |m|
13
+ remove_method m
14
+ end
15
+ end
16
+
17
+ include kd
18
+
19
+ attr_writer :strict_eql
20
+
21
+ # @param obj, the delegate
22
+ def initialize(obj=nil)
23
+ super(obj) if obj
24
+ end
25
+
26
+ #
27
+ # @return [self]
28
+ def use_strict_eql
29
+ @strict_eql = true
30
+ self
31
+ end
32
+
33
+ #
34
+ # @return [TrueClass || FalseClass]
35
+ def strict_eql?
36
+ @strict_eql ||= false
37
+ end
38
+
39
+ #
40
+ # @see Delegator
41
+ # @return obj the underlying object to delegate to
42
+ def __getobj__
43
+ @delegate_sd_obj
44
+ end
45
+
46
+ # more visually apeeling..............#sorry
47
+ alias_method :peel, :__getobj__
48
+
49
+ # change the object delegate to obj
50
+ # @see Delegator
51
+ # @param obj the object to delegate to
52
+ def __setobj__(obj)
53
+ raise ArgumentError, "cannot delegate to self" if self.equal?(obj)
54
+ @delegate_sd_obj = obj
55
+ end
56
+
57
+ # compares #object_id's if #strict_eql?
58
+ # compares the other object against @delegate_sd_obj, what are the side effects?
59
+ # @return [TrueClass || FalseClass]
60
+ def eql?(other)
61
+ # @note Facets::Kerenl::respond munges the object_id
62
+ if other.respond_to?(:__getobj__)
63
+ if strict_eql?
64
+ self.__getobj__.object_id.eql? other.__getobj__.object_id
65
+ else
66
+ self.__getobj__.eql? other.__getobj__
67
+ end
68
+ else
69
+ if strict_eql?
70
+ self.__getobj__.object_id.eql? other.object_id
71
+ else
72
+ self.__getobj__.eql? other
73
+ end
74
+ end
75
+
76
+ end #eql?
77
+
78
+ end
79
+
80
+ end
81
+ end
@@ -0,0 +1,17 @@
1
+ require 'vigilem/support/size_error'
2
+
3
+ #
4
+ #
5
+ module Vigilem::Support
6
+ class MaxSizeError < SizeError
7
+
8
+ #
9
+ # @param [Array || Hash] obj_and_max_size
10
+ # @option :obj
11
+ # @option :max_size
12
+ def initialize(obj_and_max_size)
13
+ obj_and_max_size = Hash[obj_and_max_size.zip([:obj, :max_size]).map(&:reverse)] if obj_and_max_size.is_a? Array
14
+ super("size cannot exceed #{obj_and_max_size[:max_size]} for #{obj_and_max_size[:obj]}")
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,13 @@
1
+ module Vigilem
2
+ module Support
3
+ module Metadata
4
+
5
+ #
6
+ # @return [Hash]
7
+ def metadata
8
+ @metadata ||= {}
9
+ end
10
+
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,28 @@
1
+ require 'vigilem/support/core_ext'
2
+
3
+ module Vigilem
4
+ module Support
5
+ #
6
+ # ObjectSpace like methods
7
+ module ObjSpace
8
+
9
+ #
10
+ # @return [Array]
11
+ def all
12
+ @all ||= []
13
+ end
14
+
15
+ #
16
+ # @param component
17
+ # @return [Array]
18
+ def obj_register(component)
19
+ self.all << component
20
+ if defined?(superclass) and superclass.respond_to? :obj_register
21
+ superclass.obj_register(component)
22
+ end
23
+ component
24
+ end
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,30 @@
1
+ require 'rbconfig'
2
+
3
+ module Gherkin
4
+ module CLexer
5
+ def self.singleton_method_added(method_name)
6
+ if method_name == :[] and not @overriden
7
+ @overriden = true
8
+ define_singleton_method(:[]) do |i18n_underscored_iso_code|
9
+ begin
10
+ prefix = if RbConfig::CONFIG['arch'] =~ /mswin|mingw/ && RbConfig::CONFIG['target_vendor'] != 'w64'
11
+ "#{RbConfig::CONFIG['MAJOR']}.#{RbConfig::CONFIG['MINOR']}/"
12
+ else
13
+ ''
14
+ end
15
+
16
+ lib = "#{prefix}gherkin_lexer_#{i18n_underscored_iso_code}"
17
+ require lib
18
+ const_get(i18n_underscored_iso_code.capitalize)
19
+ rescue LoadError => e
20
+ e.message << %{\nCouldn't load #{lib}\nThe $LOAD_PATH was:\n#{$LOAD_PATH.join("\n")}}
21
+ raise e
22
+ end
23
+ end
24
+ else
25
+ super(method_name)
26
+ end
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,19 @@
1
+ require 'ffi'
2
+ require 'ffi/pointer'
3
+
4
+ module FFI
5
+ class Pointer
6
+ def ==(other_obj)
7
+ return true if self.eql?(other_obj)
8
+ if other_obj.respond_to? :bytes
9
+ self.read_bytes(self.size) == other_obj.bytes
10
+ elsif other_obj.respond_to? :read_bytes and
11
+ other_obj.respond_to? :size
12
+ self.read_bytes(self.size) == other_obj.read_bytes(other_obj.size)
13
+ else
14
+ false
15
+ end
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,6 @@
1
+ module Vigilem::Support
2
+ #
3
+ #
4
+ class SizeError < ArgumentError
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ require 'vigilem/support/system'
2
+
3
+ module Vigilem::Support
4
+ Sys = System
5
+ end
@@ -0,0 +1,92 @@
1
+ module Vigilem
2
+ module Support
3
+ #
4
+ # System detection utilities
5
+ module System
6
+
7
+ SYSTEM_NAME_MASKS = { :mac => /darwin/, :windows => (win = Gem::WIN_PATTERNS.join('|')),
8
+ :win => win, :linux => /linux/, :bsd => /bsd/,
9
+ :nix => /nix|solaris|darwin|bsd|aix|hpux/, :aix => /aix/ }
10
+ #:java => /java/}
11
+
12
+ #
13
+ # @todo FFI::Platform || Fiddle::WINDOWS
14
+ # generates os_name? methods
15
+ # @return [Regexp]
16
+ SYSTEM_NAME_MASKS.each do |mask_name, mask|
17
+ define_method(:"#{mask_name}?") do
18
+ os =~ SYSTEM_NAME_MASKS[mask_name]
19
+ end
20
+ end
21
+
22
+ #
23
+ # @return [String]
24
+ def os
25
+ RbConfig::CONFIG['host_os']
26
+ end
27
+
28
+ # this will may mis-represent check out https://bugs.ruby-lang.org/issues/8568
29
+ # the size of a long
30
+ # @return [Integer]
31
+ def long_length
32
+ @long_len ||= [0].pack('L!').bytesize
33
+ end
34
+
35
+ #
36
+ # @return [TrueClass || FalseClass]
37
+ def x64bit?
38
+ @x64_bit ||= [nil].pack('p').bytesize == 8
39
+ end
40
+
41
+ #
42
+ # @return [TrueClass || FalseClass]
43
+ def x32bit?
44
+ not self.x64bit?
45
+ end
46
+
47
+ #
48
+ # @return [TrueClass || FalseClass]
49
+ def big_endian?
50
+ [1].pack('I') == [1].pack('N')
51
+ end
52
+
53
+ #
54
+ # @return [TrueClass || FalseClass]
55
+ def little_endian?
56
+ !big_endian?
57
+ end
58
+
59
+ #
60
+ # @param [Numeric] number
61
+ # @return the same number converted to a native signed long
62
+ def native_signed_long(number)
63
+ [number].pack('l!').unpack('l!').first
64
+ end
65
+
66
+ PACKVAR = 'ABCDEFGHILMNPQSUVWXZ'
67
+
68
+ # replace/supplement with Fiddle::Importer#sizeof, ruby2c, MakeMakefile#check_sizeof
69
+ # @see String#unpack
70
+ # @see Array#pack
71
+ # @param [String] format
72
+ # @return [Integer] the fize of the format
73
+ def sizeof(format)
74
+ # Only for numeric formats, String formats will raise a TypeError
75
+ elements = 0
76
+ format.scan(/[#{PACKVAR}]_?\d*/i) do |mtch|
77
+ if mtch =~ /\d+/
78
+ elements += mtch.gsub('_', '')[1..-1].to_i
79
+ elsif mtch !~ /!|_/
80
+ elements += 1
81
+ end
82
+ end
83
+ ([ 0 ] * elements).pack(format).length # bytesize?
84
+ end
85
+
86
+ extend self
87
+
88
+ end
89
+ end
90
+ end
91
+
92
+ require 'vigilem/support/sys'
@@ -0,0 +1,206 @@
1
+ require 'forwardable'
2
+
3
+ module Vigilem
4
+ module Support
5
+ # A transmutable Hash, Splits arrays into multiple keys with the same value
6
+ #
7
+ #
8
+ # {"a"=>:key1, "b"=>:key1, "c"=>:key1, "d"=>:key, "e"=>:key2, "f"=>:key2}
9
+ # becomes
10
+ #
11
+ # {:key1=>["a", "b", "c"], :key2=>["e", "f"], :key => "d"}
12
+ #
13
+ # And
14
+ #
15
+ # {:key1=>["a", "b", "c"], :key2=>["d", "e", "f"]}
16
+ # becomes
17
+ #
18
+ # {"a"=>:key1, "b"=>:key1, "c"=>:key1, "d"=>:key, "e"=>:key2, "f"=>:key2}
19
+ # And
20
+ #
21
+ # {:key1=> ['a' , ['b', 'c']]}
22
+ # becomes
23
+ #
24
+ # {"a"=>:key1, ["b", 'c']=>:key1 }
25
+ #
26
+ class TransmutableHash < Hash
27
+
28
+ extend Forwardable
29
+
30
+ # @param [Hash] hsh_or_default_value
31
+ # @param default_value
32
+ # @param [Proc] default_proc
33
+ def initialize(hsh_or_default_value={}, default_value=nil, &default_proc)
34
+ hsh, dfault = if hsh_or_default_value.is_a?(Hash)
35
+ [hsh_or_default_value, default_value]
36
+ else
37
+ [{}, hsh_or_default_value]
38
+ end
39
+ super(*dfault, &default_proc).merge!(hsh)
40
+ self.invert_default = self.default
41
+ self.invert_default_proc = self.default_proc if default_proc
42
+ end
43
+
44
+ #
45
+ # it will have a different object_id, because technically its a different hash
46
+ # not sure if that's a bug
47
+ # @return [Hash]
48
+ def invert
49
+ # did self change?
50
+ if _hash_cache_ != (temp_cache = hash)
51
+ _hash_cache_ = temp_cache
52
+ _invert_cache_ = self.class.transmute(self)
53
+ end
54
+ # if it didn't change pass off the _invert_cache_
55
+ _invert_cache_
56
+ end
57
+
58
+ #
59
+ #
60
+ def inverted?
61
+ @inverted ||= false
62
+ end
63
+
64
+ # in-place version of #invert
65
+ #
66
+ # @see TransmutableHash#invert
67
+ # @return [Hash]
68
+ def invert!
69
+ @inverted = !@inverted
70
+ self.class[replace(invert)]
71
+ end
72
+
73
+ class << self
74
+ #
75
+ #
76
+ # @param [Hash] in_hash
77
+ # @param [Hash] dest_hash
78
+ # @return [Hash] dest_hash
79
+ def transmute(in_hash, dest_hash={})
80
+ in_hash.each do |old_key, old_value|
81
+ if old_value.is_a? Array
82
+ old_value.uniq.each {|new_key| fuse_value(dest_hash, new_key, old_key) }
83
+ else
84
+ fuse_value(dest_hash, old_value, old_key)
85
+ end
86
+ end
87
+ self[dest_hash]
88
+ end
89
+
90
+ # creating somthing like ['keycode1', 'altgr', 'keycode1']
91
+ # @param [Hash] hsh
92
+ # @param key
93
+ # @param value
94
+ # @return value
95
+ def fuse_value(hsh, key, value)
96
+ if hsh.has_key?(key)
97
+ if (current_val = hsh[key]).is_a? Array
98
+ current_val.concat([value])
99
+ else
100
+ hsh[key] = [current_val, value]
101
+ end
102
+ elsif value.is_a? Array
103
+ hsh[key] = [value]
104
+ else
105
+ hsh[key] = value
106
+ end
107
+ self[hsh]
108
+ end
109
+
110
+ end
111
+
112
+ #
113
+ # @param [Array<Hash>]
114
+ # @return
115
+ def fuse!(*hashes)
116
+ hashes.each do |hsh|
117
+ hsh.each do |k, v|
118
+ self.class.fuse_value(self, k, v)
119
+ end
120
+ end
121
+ self
122
+ end
123
+
124
+ #
125
+ # @param [Array<Hash>]
126
+ # @return
127
+ def fuse(*hashes)
128
+ container = self.class.new
129
+ hashes.each do |hsh|
130
+ hsh.each do |k, v|
131
+ self.fuse_value(hsh, k, v)
132
+ end
133
+ end
134
+ container.defaults = self.defaults
135
+ container.default_procs = self.default_procs
136
+ container.fuze!(*hashes)
137
+ end
138
+
139
+ # fetches from the Hash all the values that have keys that match
140
+ # the Regexp kind of like grep
141
+ # @param [Regexp] regex
142
+ # @param [Integer] limit
143
+ # @return [Array]
144
+ def regex_fetch(regex, limit=nil)
145
+ limit ||= -1
146
+ key_list = self.keys.map {|key| [*key].grep(regex) }[0..limit].compact
147
+ key_list.map {|key| self[key] }
148
+ end
149
+
150
+ def_delegator :_invert_cache_, :default=, :invert_default=
151
+ def_delegator :_invert_cache_, :default, :invert_default
152
+ def_delegator :_invert_cache_, :default_proc=, :invert_default_proc=
153
+ def_delegator :_invert_cache_, :default_proc, :invert_default_proc
154
+
155
+ alias_method :uninvert_default=, :default=
156
+ alias_method :uninvert_default, :default
157
+ alias_method :uninvert_default_proc=, :default_proc=
158
+ alias_method :uninvert_default_proc, :default_proc
159
+
160
+ # sets the default for both self and the inverted_cache
161
+ # @see Hash#default=
162
+ # @param objs
163
+ # @return objs
164
+ def defaults=(objs)
165
+ send(:default=, [*objs].first)
166
+ _invert_cache_.default = [*objs].last
167
+ objs
168
+ end
169
+
170
+ # gets the default for both self and the inverted_cache
171
+ # @return [Array]
172
+ def defaults
173
+ [default(), invert_default]
174
+ end
175
+
176
+ # gets the default for both self and the inverted_cache
177
+ # @return [Array]
178
+ def default_procs
179
+ [default_proc(), invert_default_proc]
180
+ end
181
+
182
+ # sets the default for both self and the inverted_cache
183
+ # @param objs
184
+ # @return objs
185
+ def default_procs=(objs)
186
+ if fdprc = [*objs].first
187
+ send(:default_proc=, fdprc)
188
+ end
189
+ if ldprc = [*objs].last
190
+ _invert_cache_.default_proc = ldprc
191
+ end
192
+ objs
193
+ end
194
+
195
+ private
196
+ attr_accessor :_hash_cache_
197
+ attr_writer :_invert_cache_
198
+
199
+ # gets the cached version of the inverse
200
+ # @return [TransmutableHash]
201
+ def _invert_cache_
202
+ @_invert_cache_ ||= invert().tap {|obj| obj.instance_variable_set(:@inverted, true) }
203
+ end
204
+ end
205
+ end
206
+ end