fiddle 1.0.0.beta1 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 2fe43921484c5d31435a574dfefe01f997a7d32d
4
- data.tar.gz: e03146994af328004ad234e857040db4820f3734
2
+ SHA256:
3
+ metadata.gz: bb11df53ed0c5fb29347565ba3c56fb21ec02fe764db7f63184c1ebe5dd9ea76
4
+ data.tar.gz: 3f1571515de5917bfb3215fa45382ca59808ca94d5a0c4c966c1e924f6ed9f30
5
5
  SHA512:
6
- metadata.gz: a5ba7ff66c1000fbc80c61294523e9acba69f39bdce1f168dd748821a1fa2213204b69a3174ab74274e1343f936a8fe0a78053d4b43c6736ac7232e38e6a70d8
7
- data.tar.gz: b650a3bb827441f5a34e51e66df247c8c707383de10083f717a15500fffa020d1f5704b53558ea1b5338a3481fa968a17f2ddfa63ec51ab5b3b7c1f3fbf5a052
6
+ metadata.gz: e6f266dc69d93931746b269af9698a582f1ad59430e3a35d25073e5193d12d19a94021aac5acfdee8c8c72cda6359c2a6b528e2df7d8b695c8a23ec827e1a8c4
7
+ data.tar.gz: 884144e33963f0d549c90dbee74893663512f1e4eb216082cb332bb4fd62303969cbc77a03804b3c7f5f5b8a2916a96dc284c0857174ef88a308461633af5b0a
@@ -1,21 +1,22 @@
1
- The MIT License (MIT)
1
+ Copyright (C) 1993-2013 Yukihiro Matsumoto. All rights reserved.
2
2
 
3
- Copyright (c) 2017 SHIBATA Hiroshi
3
+ Redistribution and use in source and binary forms, with or without
4
+ modification, are permitted provided that the following conditions
5
+ are met:
6
+ 1. Redistributions of source code must retain the above copyright
7
+ notice, this list of conditions and the following disclaimer.
8
+ 2. Redistributions in binary form must reproduce the above copyright
9
+ notice, this list of conditions and the following disclaimer in the
10
+ documentation and/or other materials provided with the distribution.
4
11
 
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in
13
- all copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- THE SOFTWARE.
12
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
13
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
15
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
16
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
17
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
18
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
19
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
21
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
22
+ SUCH DAMAGE.
data/README.md CHANGED
@@ -1,8 +1,12 @@
1
1
  # Fiddle
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/fiddle`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ [![Build Status](https://travis-ci.org/ruby/fiddle.svg?branch=master)](https://travis-ci.org/ruby/fiddle)
4
4
 
5
- TODO: Delete this and the text above, and describe your gem
5
+ A libffi wrapper for Ruby.
6
+
7
+ Fiddle is an extension to translate a foreign function interface (FFI) with ruby.
8
+
9
+ It wraps [libffi](http://sourceware.org/libffi/), a popular C library which provides a portable interface that allows code written in one language to call code written in another language.
6
10
 
7
11
  ## Installation
8
12
 
@@ -22,7 +26,72 @@ Or install it yourself as:
22
26
 
23
27
  ## Usage
24
28
 
25
- TODO: Write usage instructions here
29
+ Here we will use Fiddle::Function to wrap [floor(3) from libm](http://linux.die.net/man/3/floor)
30
+
31
+ ```ruby
32
+ require 'fiddle'
33
+
34
+ libm = Fiddle.dlopen('/lib/libm.so.6')
35
+
36
+ floor = Fiddle::Function.new(
37
+ libm['floor'],
38
+ [Fiddle::TYPE_DOUBLE],
39
+ Fiddle::TYPE_DOUBLE
40
+ )
41
+
42
+ puts floor.call(3.14159) #=> 3.0
43
+ ```
44
+
45
+ ### Nested Structs
46
+
47
+ You can use hashes to create nested structs, where the hash keys are member names and the values are the nested structs:
48
+
49
+ ```ruby
50
+ StudentCollegeDetail = struct [
51
+ 'int college_id',
52
+ 'char college_name[50]'
53
+ ]
54
+
55
+ StudentDetail = struct [
56
+ 'int id',
57
+ 'char name[20]',
58
+ { clg_data: StudentCollegeDetail }
59
+ ]
60
+ ```
61
+
62
+ You can also specify an anonymous nested struct, like so:
63
+
64
+ ```ruby
65
+ StudentDetail = struct [
66
+ 'int id',
67
+ 'char name[20]',
68
+ {
69
+ clg_data: struct([
70
+ 'int college_id',
71
+ 'char college_name[50]'
72
+ ])
73
+ }
74
+ ]
75
+ ```
76
+
77
+ The position of a hash (and the order of the keys in the hash, in the case of a hash with multiple entries), dictate the offsets of the nested struct in memory. The following examples are both syntactically valid but will lay out the structs differently in memory:
78
+
79
+ ```ruby
80
+ # order of members in memory: position, id, dimensions
81
+ Rect = struct [ { position: struct(['float x', 'float y']) },
82
+ 'int id',
83
+ { dimensions: struct(['float w', 'float h']) }
84
+ ]
85
+
86
+ # order of members in memory: id, position, dimensions
87
+ Rect = struct [ 'int id',
88
+ {
89
+ position: struct(['float x', 'float y']),
90
+ dimensions: struct(['float w', 'float h'])
91
+ }
92
+ ]
93
+ ```
94
+
26
95
 
27
96
  ## Development
28
97
 
@@ -32,10 +101,9 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
32
101
 
33
102
  ## Contributing
34
103
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/hsbt/fiddle.
104
+ Bug reports and pull requests are welcome on GitHub at https://github.com/ruby/fiddle.
36
105
 
37
106
 
38
107
  ## License
39
108
 
40
- The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
41
-
109
+ The gem is available as open source under the terms of the [BSD-2-Clause](https://opensource.org/licenses/BSD-2-Clause).
data/Rakefile CHANGED
@@ -1,13 +1,11 @@
1
1
  require "bundler/gem_tasks"
2
- require "rake/testtask"
3
2
 
4
- Rake::TestTask.new(:test) do |t|
5
- t.libs << "test" << "test/lib"
6
- t.libs << "lib"
7
- t.test_files = FileList['test/**/test_*.rb']
3
+ desc "Run test"
4
+ task :test do
5
+ ruby("test/run.rb")
8
6
  end
9
7
 
10
8
  require 'rake/extensiontask'
11
9
  Rake::ExtensionTask.new("fiddle")
12
10
 
13
- task :default => :test
11
+ task :default => [:compile, :test]
@@ -0,0 +1,331 @@
1
+ # Used by configure and make to download or update mirrored Ruby and GCC
2
+ # files. This will use HTTPS if possible, falling back to HTTP.
3
+
4
+ require 'fileutils'
5
+ require 'open-uri'
6
+ require 'pathname'
7
+ begin
8
+ require 'net/https'
9
+ rescue LoadError
10
+ https = 'http'
11
+ else
12
+ https = 'https'
13
+
14
+ # open-uri of ruby 2.2.0 accept an array of PEMs as ssl_ca_cert, but old
15
+ # versions are not. so, patching OpenSSL::X509::Store#add_file instead.
16
+ class OpenSSL::X509::Store
17
+ alias orig_add_file add_file
18
+ def add_file(pems)
19
+ Array(pems).each do |pem|
20
+ if File.directory?(pem)
21
+ add_path pem
22
+ else
23
+ orig_add_file pem
24
+ end
25
+ end
26
+ end
27
+ end
28
+ # since open-uri internally checks ssl_ca_cert using File.directory?,
29
+ # allow to accept an array.
30
+ class <<File
31
+ alias orig_directory? directory?
32
+ def File.directory? files
33
+ files.is_a?(Array) ? false : orig_directory?(files)
34
+ end
35
+ end
36
+ end
37
+
38
+ class Downloader
39
+ def self.https=(https)
40
+ @@https = https
41
+ end
42
+
43
+ def self.https?
44
+ @@https == 'https'
45
+ end
46
+
47
+ def self.https
48
+ @@https
49
+ end
50
+
51
+ class GNU < self
52
+ def self.download(name, *rest)
53
+ if https?
54
+ super("https://raw.githubusercontent.com/gcc-mirror/gcc/master/#{name}", name, *rest)
55
+ else
56
+ super("https://repo.or.cz/official-gcc.git/blob_plain/HEAD:/#{name}", name, *rest)
57
+ end
58
+ end
59
+ end
60
+
61
+ class RubyGems < self
62
+ def self.download(name, dir = nil, since = true, options = {})
63
+ require 'rubygems'
64
+ options = options.dup
65
+ options[:ssl_ca_cert] = Dir.glob(File.expand_path("../lib/rubygems/ssl_certs/**/*.pem", File.dirname(__FILE__)))
66
+ super("https://rubygems.org/downloads/#{name}", name, dir, since, options)
67
+ end
68
+ end
69
+
70
+ Gems = RubyGems
71
+
72
+ class Unicode < self
73
+ def self.download(name, *rest)
74
+ super("http://www.unicode.org/Public/#{name}", name, *rest)
75
+ end
76
+ end
77
+
78
+ def self.mode_for(data)
79
+ /\A#!/ =~ data ? 0755 : 0644
80
+ end
81
+
82
+ def self.http_options(file, since)
83
+ options = {}
84
+ if since
85
+ case since
86
+ when true
87
+ since = (File.mtime(file).httpdate rescue nil)
88
+ when Time
89
+ since = since.httpdate
90
+ end
91
+ if since
92
+ options['If-Modified-Since'] = since
93
+ end
94
+ end
95
+ options['Accept-Encoding'] = '*' # to disable Net::HTTP::GenericRequest#decode_content
96
+ options
97
+ end
98
+
99
+ # Downloader.download(url, name, [dir, [since]])
100
+ #
101
+ # Update a file from url if newer version is available.
102
+ # Creates the file if the file doesn't yet exist; however, the
103
+ # directory where the file is being created has to exist already.
104
+ # The +since+ parameter can take the following values, with associated meanings:
105
+ # true ::
106
+ # Take the last-modified time of the current file on disk, and only download
107
+ # if the server has a file that was modified later. Download unconditionally
108
+ # if we don't have the file yet. Default.
109
+ # +some time value+ ::
110
+ # Use this time value instead of the time of modification of the file on disk.
111
+ # nil ::
112
+ # Only download the file if it doesn't exist yet.
113
+ # false ::
114
+ # always download url regardless of whether we already have a file,
115
+ # and regardless of modification times. (This is essentially just a waste of
116
+ # network resources, except in the case that the file we have is somehow damaged.
117
+ # Please note that using this recurringly might create or be seen as a
118
+ # denial of service attack.)
119
+ #
120
+ # Example usage:
121
+ # download 'http://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt',
122
+ # 'UnicodeData.txt', 'enc/unicode/data'
123
+ def self.download(url, name, dir = nil, since = true, options = {})
124
+ options = options.dup
125
+ url = URI(url)
126
+ dryrun = options.delete(:dryrun)
127
+ if name
128
+ file = Pathname.new(under(dir, name))
129
+ else
130
+ name = File.basename(url.path)
131
+ end
132
+ cache_save = options.delete(:cache_save) {
133
+ ENV["CACHE_SAVE"] != "no"
134
+ }
135
+ cache = cache_file(url, name, options.delete(:cache_dir))
136
+ file ||= cache
137
+ if since.nil? and file.exist?
138
+ if $VERBOSE
139
+ $stdout.puts "#{file} already exists"
140
+ $stdout.flush
141
+ end
142
+ if cache_save
143
+ save_cache(cache, file, name)
144
+ end
145
+ return file.to_path
146
+ end
147
+ if dryrun
148
+ puts "Download #{url} into #{file}"
149
+ return
150
+ end
151
+ if link_cache(cache, file, name, $VERBOSE)
152
+ return file.to_path
153
+ end
154
+ if !https? and URI::HTTPS === url
155
+ warn "*** using http instead of https ***"
156
+ url.scheme = 'http'
157
+ url = URI(url.to_s)
158
+ end
159
+ if $VERBOSE
160
+ $stdout.print "downloading #{name} ... "
161
+ $stdout.flush
162
+ end
163
+ begin
164
+ data = url.read(options.merge(http_options(file, since.nil? ? true : since)))
165
+ rescue OpenURI::HTTPError => http_error
166
+ if http_error.message =~ /^304 / # 304 Not Modified
167
+ if $VERBOSE
168
+ $stdout.puts "#{name} not modified"
169
+ $stdout.flush
170
+ end
171
+ return file.to_path
172
+ end
173
+ raise
174
+ rescue Timeout::Error
175
+ if since.nil? and file.exist?
176
+ puts "Request for #{url} timed out, using old version."
177
+ return file.to_path
178
+ end
179
+ raise
180
+ rescue SocketError
181
+ if since.nil? and file.exist?
182
+ puts "No network connection, unable to download #{url}, using old version."
183
+ return file.to_path
184
+ end
185
+ raise
186
+ end
187
+ mtime = nil
188
+ dest = (cache_save && cache && !cache.exist? ? cache : file)
189
+ dest.parent.mkpath
190
+ dest.open("wb", 0600) do |f|
191
+ f.write(data)
192
+ f.chmod(mode_for(data))
193
+ mtime = data.meta["last-modified"]
194
+ end
195
+ if mtime
196
+ mtime = Time.httpdate(mtime)
197
+ dest.utime(mtime, mtime)
198
+ end
199
+ if $VERBOSE
200
+ $stdout.puts "done"
201
+ $stdout.flush
202
+ end
203
+ if dest.eql?(cache)
204
+ link_cache(cache, file, name)
205
+ elsif cache_save
206
+ save_cache(cache, file, name)
207
+ end
208
+ return file.to_path
209
+ rescue => e
210
+ raise "failed to download #{name}\n#{e.message}: #{url}"
211
+ end
212
+
213
+ def self.under(dir, name)
214
+ dir ? File.join(dir, File.basename(name)) : name
215
+ end
216
+
217
+ def self.cache_file(url, name, cache_dir = nil)
218
+ case cache_dir
219
+ when false
220
+ return nil
221
+ when nil
222
+ cache_dir = ENV['CACHE_DIR']
223
+ if !cache_dir or cache_dir.empty?
224
+ cache_dir = ".downloaded-cache"
225
+ end
226
+ end
227
+ Pathname.new(cache_dir) + (name || File.basename(URI(url).path))
228
+ end
229
+
230
+ def self.link_cache(cache, file, name, verbose = false)
231
+ return false unless cache and cache.exist?
232
+ return true if cache.eql?(file)
233
+ if /cygwin/ !~ RUBY_PLATFORM or /winsymlink:nativestrict/ =~ ENV['CYGWIN']
234
+ begin
235
+ file.make_symlink(cache.relative_path_from(file.parent))
236
+ rescue SystemCallError
237
+ else
238
+ if verbose
239
+ $stdout.puts "made symlink #{name} to #{cache}"
240
+ $stdout.flush
241
+ end
242
+ return true
243
+ end
244
+ end
245
+ begin
246
+ file.make_link(cache)
247
+ rescue SystemCallError
248
+ else
249
+ if verbose
250
+ $stdout.puts "made link #{name} to #{cache}"
251
+ $stdout.flush
252
+ end
253
+ return true
254
+ end
255
+ end
256
+
257
+ def self.save_cache(cache, file, name)
258
+ if cache and !cache.eql?(file) and !cache.exist?
259
+ begin
260
+ file.rename(cache)
261
+ rescue
262
+ else
263
+ link_cache(cache, file, name)
264
+ end
265
+ end
266
+ end
267
+ end
268
+
269
+ Downloader.https = https.freeze
270
+
271
+ if $0 == __FILE__
272
+ since = true
273
+ options = {}
274
+ until ARGV.empty?
275
+ case ARGV[0]
276
+ when '-d'
277
+ destdir = ARGV[1]
278
+ ARGV.shift
279
+ when '-p'
280
+ # strip directory names from the name to download, and add the
281
+ # prefix instead.
282
+ prefix = ARGV[1]
283
+ ARGV.shift
284
+ when '-e'
285
+ since = nil
286
+ when '-a'
287
+ since = false
288
+ when '-n', '--dryrun'
289
+ options[:dryrun] = true
290
+ when '--cache-dir'
291
+ options[:cache_dir] = ARGV[1]
292
+ ARGV.shift
293
+ when /\A--cache-dir=(.*)/m
294
+ options[:cache_dir] = $1
295
+ when /\A-/
296
+ abort "#{$0}: unknown option #{ARGV[0]}"
297
+ else
298
+ break
299
+ end
300
+ ARGV.shift
301
+ end
302
+ dl = Downloader.constants.find do |name|
303
+ ARGV[0].casecmp(name.to_s) == 0
304
+ end unless ARGV.empty?
305
+ $VERBOSE = true
306
+ if dl
307
+ dl = Downloader.const_get(dl)
308
+ ARGV.shift
309
+ ARGV.each do |name|
310
+ dir = destdir
311
+ if prefix
312
+ name = name.sub(/\A\.\//, '')
313
+ if name.start_with?(destdir+"/")
314
+ name = name[(destdir.size+1)..-1]
315
+ if (dir = File.dirname(name)) == '.'
316
+ dir = destdir
317
+ else
318
+ dir = File.join(destdir, dir)
319
+ end
320
+ else
321
+ name = File.basename(name)
322
+ end
323
+ name = "#{prefix}/#{name}"
324
+ end
325
+ dl.download(name, dir, since, options)
326
+ end
327
+ else
328
+ abort "usage: #{$0} url name" unless ARGV.size == 2
329
+ Downloader.download(ARGV[0], ARGV[1], destdir, since, options)
330
+ end
331
+ end