vigilem-support 0.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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