ffi 0.6.4 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of ffi might be problematic. Click here for more details.

Files changed (92) hide show
  1. data/History.txt +7 -0
  2. data/LICENSE +10 -21
  3. data/README.rdoc +70 -0
  4. data/Rakefile +56 -84
  5. data/ext/ffi_c/AbstractMemory.c +56 -38
  6. data/ext/ffi_c/AbstractMemory.h +15 -22
  7. data/ext/ffi_c/Buffer.c +61 -22
  8. data/ext/ffi_c/Call.c +52 -540
  9. data/ext/ffi_c/Call.h +1 -1
  10. data/ext/ffi_c/DataConverter.c +62 -0
  11. data/ext/ffi_c/DynamicLibrary.c +21 -1
  12. data/ext/ffi_c/Function.c +252 -30
  13. data/ext/ffi_c/MappedType.c +146 -0
  14. data/{libtest/FunctionTest.c → ext/ffi_c/MappedType.h} +32 -25
  15. data/ext/ffi_c/MemoryPointer.c +12 -33
  16. data/ext/ffi_c/Platform.c +2 -0
  17. data/ext/ffi_c/Pointer.c +66 -28
  18. data/ext/ffi_c/Struct.c +19 -306
  19. data/ext/ffi_c/Struct.h +6 -0
  20. data/ext/ffi_c/StructByReference.c +150 -0
  21. data/{libtest/LastErrorTest.c → ext/ffi_c/StructByReference.h} +30 -21
  22. data/ext/ffi_c/StructLayout.c +26 -16
  23. data/ext/ffi_c/Type.c +39 -68
  24. data/ext/ffi_c/Type.h +12 -22
  25. data/ext/ffi_c/Types.c +20 -5
  26. data/ext/ffi_c/Types.h +7 -7
  27. data/ext/ffi_c/Variadic.c +21 -17
  28. data/ext/ffi_c/extconf.rb +4 -0
  29. data/ext/ffi_c/ffi.c +8 -2
  30. data/ext/ffi_c/rbffi.h +1 -0
  31. data/lib/ffi/autopointer.rb +23 -22
  32. data/lib/ffi/enum.rb +36 -21
  33. data/lib/ffi/errno.rb +20 -0
  34. data/lib/ffi/ffi.rb +13 -80
  35. data/lib/ffi/io.rb +12 -20
  36. data/lib/ffi/library.rb +109 -92
  37. data/lib/ffi/managedstruct.rb +1 -1
  38. data/lib/ffi/memorypointer.rb +15 -21
  39. data/lib/ffi/platform.rb +27 -33
  40. data/lib/ffi/pointer.rb +14 -21
  41. data/lib/ffi/struct.rb +98 -49
  42. data/lib/ffi/struct_layout_builder.rb +158 -0
  43. data/lib/ffi/types.rb +99 -128
  44. data/lib/ffi/union.rb +20 -0
  45. data/lib/ffi/variadic.rb +33 -22
  46. data/spec/ffi/async_callback_spec.rb +23 -0
  47. data/spec/ffi/callback_spec.rb +62 -0
  48. data/spec/ffi/custom_param_type.rb +31 -0
  49. data/spec/ffi/custom_type_spec.rb +73 -0
  50. data/spec/ffi/enum_spec.rb +19 -0
  51. data/spec/ffi/ffi_spec.rb +24 -0
  52. data/spec/ffi/pointer_spec.rb +15 -0
  53. data/spec/ffi/rbx/memory_pointer_spec.rb +7 -1
  54. data/spec/ffi/strptr_spec.rb +36 -0
  55. data/spec/ffi/struct_packed_spec.rb +46 -0
  56. data/spec/ffi/struct_spec.rb +19 -5
  57. data/spec/ffi/typedef_spec.rb +14 -0
  58. data/tasks/ann.rake +80 -0
  59. data/tasks/extension.rake +25 -0
  60. data/tasks/gem.rake +200 -0
  61. data/tasks/git.rake +41 -0
  62. data/tasks/notes.rake +27 -0
  63. data/tasks/post_load.rake +34 -0
  64. data/tasks/rdoc.rake +50 -0
  65. data/tasks/rubyforge.rake +55 -0
  66. data/tasks/setup.rb +301 -0
  67. data/tasks/spec.rake +54 -0
  68. data/tasks/svn.rake +47 -0
  69. data/tasks/test.rake +40 -0
  70. metadata +139 -131
  71. data/README.md +0 -109
  72. data/ext/ffi_c/AutoPointer.c +0 -60
  73. data/ext/ffi_c/AutoPointer.h +0 -18
  74. data/ext/ffi_c/Ffi_c.iml +0 -12
  75. data/ffi.gemspec +0 -18
  76. data/gen/log +0 -1
  77. data/lib/Lib.iml +0 -21
  78. data/libtest/Benchmark.c +0 -73
  79. data/libtest/BoolTest.c +0 -52
  80. data/libtest/BufferTest.c +0 -52
  81. data/libtest/ClosureTest.c +0 -173
  82. data/libtest/EnumTest.c +0 -55
  83. data/libtest/GNUmakefile +0 -141
  84. data/libtest/GlobalVariable.c +0 -56
  85. data/libtest/NumberTest.c +0 -145
  86. data/libtest/PointerTest.c +0 -84
  87. data/libtest/ReferenceTest.c +0 -44
  88. data/libtest/StringTest.c +0 -55
  89. data/libtest/StructTest.c +0 -247
  90. data/libtest/UnionTest.c +0 -64
  91. data/libtest/VariadicTest.c +0 -57
  92. data/spec/ffi/Ffi.iml +0 -12
data/History.txt CHANGED
@@ -1,3 +1,10 @@
1
+ == 1.0.0 / 2010-11-30
2
+ * Major improvements
3
+ * Better handling of non-ruby thread callbacks
4
+ * Support for releasing the GIL during C function calls
5
+ * Minor improvements
6
+ * code cleanups
7
+
1
8
  == 0.5.0 / 2009-10-06
2
9
 
3
10
  * Major improvements
data/LICENSE CHANGED
@@ -1,25 +1,14 @@
1
- Copyright (c) 2008, 2009 Ruby FFI contributors
1
+ Copyright (c) 2008-2010 Ruby-FFI contributors
2
2
  All rights reserved.
3
3
 
4
- Redistribution and use in source and binary forms, with or without
5
- modification, are permitted provided that the following conditions are met:
4
+ This code is free software: you can redistribute it and/or modify it under
5
+ the terms of the GNU Lesser General Public License version 3 only, as
6
+ published by the Free Software Foundation.
6
7
 
7
- * Redistributions of source code must retain the above copyright notice, this
8
- list of conditions and the following disclaimer.
9
- * Redistributions in binary form must reproduce the above copyright notice
10
- this list of conditions and the following disclaimer in the documentation
11
- and/or other materials provided with the distribution.
12
- * Neither the name of the JRuby Project nor the names of its contributors
13
- may be used to endorse or promote products derived from this software
14
- without specific prior written permission.
8
+ This code is distributed in the hope that it will be useful, but WITHOUT
9
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
11
+ version 3 for more details.
15
12
 
16
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23
- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24
- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13
+ You should have received a copy of the GNU Lesser General Public License
14
+ version 3 along with this work. If not, see <http://www.gnu.org/licenses/>.
data/README.rdoc ADDED
@@ -0,0 +1,70 @@
1
+ ruby-ffi
2
+ by Wayne Meissner
3
+ http://wiki.github.com/ffi/ffi
4
+
5
+ == DESCRIPTION:
6
+
7
+ Ruby-FFI is a ruby extension for programmatically loading dynamic
8
+ libraries, binding functions within them, and calling those functions
9
+ from Ruby code. Moreover, a Ruby-FFI extension works without changes
10
+ on Ruby and JRuby. Discover why should you write your next extension
11
+ using Ruby-FFI here[http://wiki.github.com/ffi/ffi/why-use-ffi].
12
+
13
+ == FEATURES/PROBLEMS:
14
+
15
+ * It has a very intuitive DSL
16
+ * It supports all C native types
17
+ * It supports C structs (also nested), enums and global variables
18
+ * It supports callbacks
19
+ * It has smart methods to handle memory management of pointers and structs
20
+
21
+ == SYNOPSIS:
22
+
23
+ require 'ffi'
24
+
25
+ module MyLib
26
+ extend FFI::Library
27
+ ffi_lib 'c'
28
+ attach_function :puts, [ :string ], :int
29
+ end
30
+
31
+ MyLib.puts 'Hello boys using libc!'
32
+
33
+ For less minimalistic and more sane examples you may look at:
34
+
35
+ * the samples/ folder
36
+ * the examples on the wiki[http://wiki.github.com/ffi/ffi]
37
+ * the projects using FFI listed on this page[http://wiki.github.com/ffi/ffi/projects-using-ffi]
38
+
39
+ == REQUIREMENTS:
40
+
41
+ * You need a sane building environment in order to compile the extension.
42
+
43
+ == DOWNLOAD/INSTALL:
44
+
45
+ From rubyforge:
46
+
47
+ [sudo] gem install ffi
48
+
49
+ or from the git repository on github:
50
+
51
+ git clone git://github.com/ffi/ffi.git
52
+ cd ffi
53
+ rake gem:install
54
+
55
+ == CREDITS:
56
+
57
+ Special thanks to:
58
+
59
+ * Yehuda Katz
60
+ * Luc Heinrich
61
+ * Andrea Fazzi
62
+ * Mike Dalessio
63
+ * Hongli Lai
64
+ * Evan Phoenix
65
+ * Aman Gupta
66
+ * Beoran
67
+
68
+ == LICENSE:
69
+
70
+ See LICENSE file.
data/Rakefile CHANGED
@@ -1,31 +1,32 @@
1
1
  require 'rubygems'
2
- require 'rubygems/package_task'
3
2
  require 'rbconfig'
4
3
 
5
4
  USE_RAKE_COMPILER = (RUBY_PLATFORM =~ /java/) ? false : true
6
5
  if USE_RAKE_COMPILER
7
6
  gem 'rake-compiler', '>=0.6.0'
8
7
  require 'rake/extensiontask'
8
+ ENV['RUBY_CC_VERSION'] = '1.8.6:1.9.1'
9
9
  end
10
10
 
11
11
  require 'date'
12
12
  require 'fileutils'
13
13
  require 'rbconfig'
14
14
 
15
+ load 'tasks/setup.rb'
15
16
 
16
- LIBEXT = case RbConfig::CONFIG['host_os'].downcase
17
+ LIBEXT = case Config::CONFIG['host_os'].downcase
17
18
  when /darwin/
18
19
  "dylib"
19
20
  when /mswin|mingw/
20
21
  "dll"
21
22
  else
22
- RbConfig::CONFIG['DLEXT']
23
+ Config::CONFIG['DLEXT']
23
24
  end
24
25
 
25
- CPU = case RbConfig::CONFIG['host_cpu'].downcase
26
+ CPU = case Config::CONFIG['host_cpu'].downcase
26
27
  when /i[3456]86/
27
28
  # Darwin always reports i686, even when running in 64bit mode
28
- if RbConfig::CONFIG['host_os'] =~ /darwin/ && 0xfee1deadbeef.is_a?(Fixnum)
29
+ if Config::CONFIG['host_os'] =~ /darwin/ && 0xfee1deadbeef.is_a?(Fixnum)
29
30
  "x86_64"
30
31
  else
31
32
  "i386"
@@ -40,14 +41,11 @@ CPU = case RbConfig::CONFIG['host_cpu'].downcase
40
41
  when /ppc|powerpc/
41
42
  "powerpc"
42
43
 
43
- when /^arm/
44
- "arm"
45
-
46
44
  else
47
- RbConfig::CONFIG['host_cpu']
45
+ Config::CONFIG['host_cpu']
48
46
  end
49
47
 
50
- OS = case RbConfig::CONFIG['host_os'].downcase
48
+ OS = case Config::CONFIG['host_os'].downcase
51
49
  when /linux/
52
50
  "linux"
53
51
  when /darwin/
@@ -61,48 +59,78 @@ OS = case RbConfig::CONFIG['host_os'].downcase
61
59
  when /mswin|mingw/
62
60
  "win32"
63
61
  else
64
- RbConfig::CONFIG['host_os'].downcase
62
+ Config::CONFIG['host_os'].downcase
65
63
  end
66
64
 
67
- CC = ENV['CC'] || RbConfig::CONFIG['CC'] || "gcc"
65
+ CC=ENV['CC'] || Config::CONFIG['CC'] || "gcc"
68
66
 
69
- GMAKE = system('which gmake >/dev/null') && 'gmake' || 'make'
67
+ GMAKE = Config::CONFIG['host_os'].downcase =~ /bsd|solaris/ ? "gmake" : "make"
70
68
 
71
69
  LIBTEST = "build/libtest.#{LIBEXT}"
72
70
  BUILD_DIR = "build"
73
- BUILD_EXT_DIR = File.join(BUILD_DIR, "#{RbConfig::CONFIG['arch']}", 'ffi_c', RUBY_VERSION)
71
+ BUILD_EXT_DIR = File.join(BUILD_DIR, "#{Config::CONFIG['arch']}", 'ffi_c', RUBY_VERSION)
74
72
 
75
- def gem_spec
76
- @gem_spec ||= Gem::Specification.load('ffi.gemspec')
77
- end
73
+ # Project general information
74
+ PROJ.name = 'ffi'
75
+ PROJ.authors = 'Wayne Meissner'
76
+ PROJ.email = 'wmeissner@gmail.com'
77
+ PROJ.url = 'http://wiki.github.com/ffi/ffi'
78
+ PROJ.version = '1.0.0'
79
+ PROJ.rubyforge.name = 'ffi'
80
+ PROJ.readme_file = 'README.rdoc'
78
81
 
79
- Gem::PackageTask.new(gem_spec) do |pkg|
80
- pkg.need_zip = true
81
- pkg.need_tar = true
82
- pkg.package_dir = 'pkg'
83
- end
82
+ # Annoucement
83
+ PROJ.ann.paragraphs << 'FEATURES' << 'SYNOPSIS' << 'REQUIREMENTS' << 'DOWNLOAD/INSTALL' << 'CREDITS' << 'LICENSE'
84
+
85
+ PROJ.ann.email[:from] = 'andrea.fazzi@alcacoop.it'
86
+ PROJ.ann.email[:to] = ['ruby-ffi@googlegroups.com']
87
+ PROJ.ann.email[:server] = 'smtp.gmail.com'
88
+
89
+ # Gem specifications
90
+ PROJ.gem.need_tar = false
91
+ PROJ.gem.files = %w(History.txt LICENSE README.rdoc Rakefile) + Dir.glob("{ext,gen,lib,spec,tasks}/**/*")
92
+ PROJ.gem.platform = Gem::Platform::RUBY
93
+
94
+ # Override Mr. Bones autogenerated extensions and force ours in
95
+ PROJ.gem.extras['extensions'] = %w(ext/ffi_c/extconf.rb gen/Rakefile)
96
+
97
+ # RDoc
98
+ PROJ.rdoc.exclude << '^ext\/'
99
+ PROJ.rdoc.opts << '-x' << 'ext'
100
+
101
+ # Ruby
102
+ PROJ.ruby_opts = []
103
+ PROJ.ruby_opts << '-I' << BUILD_EXT_DIR unless RUBY_PLATFORM == "java"
104
+
105
+ # RSpec
106
+ PROJ.spec.files.exclude /rbx/
107
+ PROJ.spec.opts << '--color' << '-fs'
108
+
109
+ # Dependencies
110
+
111
+ depend_on 'rake', '>=0.8.7'
84
112
 
85
113
  TEST_DEPS = [ LIBTEST ]
86
114
  if RUBY_PLATFORM == "java"
87
115
  desc "Run all specs"
88
116
  task :specs => TEST_DEPS do
89
- sh %{#{Gem.ruby} -w -S rspec #{Dir["spec/ffi/*_spec.rb"].join(" ")} -fs --color}
117
+ sh %{#{Gem.ruby} -S spec #{Dir["spec/ffi/*_spec.rb"].join(" ")} -fs --color}
90
118
  end
91
119
  desc "Run rubinius specs"
92
120
  task :rbxspecs => TEST_DEPS do
93
- sh %{#{Gem.ruby} -w -S rspec #{Dir["spec/ffi/rbx/*_spec.rb"].join(" ")} -fs --color}
121
+ sh %{#{Gem.ruby} -S spec #{Dir["spec/ffi/rbx/*_spec.rb"].join(" ")} -fs --color}
94
122
  end
95
123
  else
96
124
  TEST_DEPS.unshift :compile
97
125
  desc "Run all specs"
98
126
  task :specs => TEST_DEPS do
99
127
  ENV["MRI_FFI"] = "1"
100
- sh %{#{Gem.ruby} -w -Ilib -I#{BUILD_EXT_DIR} -S rspec #{Dir["spec/ffi/*_spec.rb"].join(" ")} -fs --color}
128
+ sh %{#{Gem.ruby} -Ilib -I#{BUILD_EXT_DIR} -S spec #{Dir["spec/ffi/*_spec.rb"].join(" ")} -fs --color}
101
129
  end
102
130
  desc "Run rubinius specs"
103
131
  task :rbxspecs => TEST_DEPS do
104
132
  ENV["MRI_FFI"] = "1"
105
- sh %{#{Gem.ruby} -w -Ilib -I#{BUILD_EXT_DIR} -S rspec #{Dir["spec/ffi/rbx/*_spec.rb"].join(" ")} -fs --color}
133
+ sh %{#{Gem.ruby} -Ilib -I#{BUILD_EXT_DIR} -S spec #{Dir["spec/ffi/rbx/*_spec.rb"].join(" ")} -fs --color}
106
134
  end
107
135
  end
108
136
 
@@ -112,16 +140,11 @@ task :package => 'gem:package'
112
140
  desc "Install the gem locally"
113
141
  task :install => 'gem:install'
114
142
 
115
- namespace :gem do
116
- task :install => :gem do
117
- ruby %{ -S gem install pkg/ffi-#{gem_spec.version}.gem }
118
- end
119
- end
120
143
 
121
144
  desc "Clean all built files"
122
145
  task :distclean => :clobber do
123
146
  FileUtils.rm_rf('build')
124
- FileUtils.rm_rf(Dir["lib/**/ffi_c.#{RbConfig::CONFIG['DLEXT']}"])
147
+ FileUtils.rm_rf(Dir["lib/**/ffi_c.#{Config::CONFIG['DLEXT']}"])
125
148
  FileUtils.rm_rf('lib/1.8')
126
149
  FileUtils.rm_rf('lib/1.9')
127
150
  FileUtils.rm_rf('lib/ffi/types.conf')
@@ -131,7 +154,7 @@ end
131
154
 
132
155
 
133
156
  desc "Build the native test lib"
134
- file "build/libtest.#{LIBEXT}" => FileList['libtest/**/*.[ch]'] do
157
+ task "build/libtest.#{LIBEXT}" do
135
158
  sh %{#{GMAKE} -f libtest/GNUmakefile CPU=#{CPU} OS=#{OS} }
136
159
  end
137
160
 
@@ -164,54 +187,3 @@ task 'spec:specdoc' => TEST_DEPS
164
187
 
165
188
  task :default => :specs
166
189
 
167
- task 'gem:win32' do
168
- sh("rake cross native gem RUBY_CC_VERSION='1.8.7:1.9.3'") || raise("win32 build failed!")
169
- end
170
-
171
-
172
- namespace 'java' do
173
-
174
- java_gem_spec = Gem::Specification.new do |s|
175
- s.name = gem_spec.name
176
- s.version = gem_spec.version
177
- s.author = gem_spec.author
178
- s.email = gem_spec.email
179
- s.homepage = gem_spec.homepage
180
- s.summary = gem_spec.summary
181
- s.description = gem_spec.description
182
- s.files = %w(History.txt LICENSE COPYING COPYING.LESSER README.md Rakefile)
183
- s.has_rdoc = false
184
- s.license = gem_spec.license
185
- s.platform = 'java'
186
- end
187
-
188
- Gem::PackageTask.new(java_gem_spec) do |pkg|
189
- pkg.need_zip = true
190
- pkg.need_tar = true
191
- pkg.package_dir = 'pkg'
192
- end
193
- end
194
-
195
- task 'gem:java' => 'java:gem'
196
-
197
-
198
- if USE_RAKE_COMPILER
199
- Rake::ExtensionTask.new('ffi_c', gem_spec) do |ext|
200
- ext.name = 'ffi_c' # indicate the name of the extension.
201
- # ext.lib_dir = BUILD_DIR # put binaries into this folder.
202
- ext.tmp_dir = BUILD_DIR # temporary folder used during compilation.
203
- ext.cross_compile = true # enable cross compilation (requires cross compile toolchain)
204
- ext.cross_platform = 'i386-mingw32' # forces the Windows platform instead of the default one
205
- end
206
- end
207
-
208
- begin
209
- require 'yard'
210
-
211
- namespace :doc do
212
- YARD::Rake::YardocTask.new do |yard|
213
- end
214
- end
215
- rescue LoadError
216
- warn "[warn] YARD unavailable"
217
- end
@@ -3,33 +3,26 @@
3
3
  *
4
4
  * All rights reserved.
5
5
  *
6
- * Redistribution and use in source and binary forms, with or without
7
- * modification, are permitted provided that the following conditions are met:
6
+ * This file is part of ruby-ffi.
8
7
  *
9
- * * Redistributions of source code must retain the above copyright notice, this
10
- * list of conditions and the following disclaimer.
11
- * * Redistributions in binary form must reproduce the above copyright notice
12
- * this list of conditions and the following disclaimer in the documentation
13
- * and/or other materials provided with the distribution.
14
- * * The name of the author or authors may not be used to endorse or promote
15
- * products derived from this software without specific prior written permission.
8
+ * This code is free software: you can redistribute it and/or modify it under
9
+ * the terms of the GNU Lesser General Public License version 3 only, as
10
+ * published by the Free Software Foundation.
16
11
  *
17
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
21
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
12
+ * This code is distributed in the hope that it will be useful, but WITHOUT
13
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
15
+ * version 3 for more details.
16
+ *
17
+ * You should have received a copy of the GNU Lesser General Public License
18
+ * version 3 along with this work. If not, see <http://www.gnu.org/licenses/>.
27
19
  */
28
20
 
29
21
  #include <sys/types.h>
30
22
  #include <sys/param.h>
31
23
  #include <stdint.h>
32
24
  #include <stdbool.h>
25
+ #include <limits.h>
33
26
  #include <ruby.h>
34
27
  #include "rbffi.h"
35
28
  #include "compat.h"
@@ -49,17 +42,18 @@ memory_allocate(VALUE klass)
49
42
  AbstractMemory* memory;
50
43
  VALUE obj;
51
44
  obj = Data_Make_Struct(klass, AbstractMemory, NULL, -1, memory);
52
- memory->access = MEM_RD | MEM_WR;
45
+ memory->flags = MEM_RD | MEM_WR;
53
46
 
54
47
  return obj;
55
48
  }
49
+ #define VAL(x, swap) (unlikely(((memory->flags & MEM_SWAP) != 0)) ? swap((x)) : (x))
56
50
 
57
- #define NUM_OP(name, type, toNative, fromNative) \
51
+ #define NUM_OP(name, type, toNative, fromNative, swap) \
58
52
  static void memory_op_put_##name(AbstractMemory* memory, long off, VALUE value); \
59
53
  static void \
60
54
  memory_op_put_##name(AbstractMemory* memory, long off, VALUE value) \
61
55
  { \
62
- type tmp = (type) toNative(value); \
56
+ type tmp = (type) VAL(toNative(value), swap); \
63
57
  checkWrite(memory); \
64
58
  checkBounds(memory, off, sizeof(type)); \
65
59
  memcpy(memory->address + off, &tmp, sizeof(tmp)); \
@@ -81,7 +75,7 @@ memory_op_get_##name(AbstractMemory* memory, long off) \
81
75
  checkRead(memory); \
82
76
  checkBounds(memory, off, sizeof(type)); \
83
77
  memcpy(&tmp, memory->address + off, sizeof(tmp)); \
84
- return fromNative(tmp); \
78
+ return fromNative(VAL(tmp, swap)); \
85
79
  } \
86
80
  static VALUE memory_get_##name(VALUE self, VALUE offset); \
87
81
  static VALUE \
@@ -104,7 +98,7 @@ memory_put_array_of_##name(VALUE self, VALUE offset, VALUE ary) \
104
98
  checkWrite(memory); \
105
99
  checkBounds(memory, off, count * sizeof(type)); \
106
100
  for (i = 0; i < count; i++) { \
107
- type tmp = (type) toNative(RARRAY_PTR(ary)[i]); \
101
+ type tmp = (type) VAL(toNative(RARRAY_PTR(ary)[i]), swap); \
108
102
  memcpy(memory->address + off + (i * sizeof(type)), &tmp, sizeof(tmp)); \
109
103
  } \
110
104
  return self; \
@@ -123,23 +117,47 @@ memory_get_array_of_##name(VALUE self, VALUE offset, VALUE length) \
123
117
  for (i = 0; i < count; ++i) { \
124
118
  type tmp; \
125
119
  memcpy(&tmp, memory->address + off + (i * sizeof(type)), sizeof(tmp)); \
126
- rb_ary_push(retVal, fromNative(tmp)); \
120
+ rb_ary_push(retVal, fromNative(VAL(tmp, swap))); \
127
121
  } \
128
122
  return retVal; \
129
123
  }
130
124
 
131
- NUM_OP(int8, int8_t, NUM2INT, INT2NUM);
132
- NUM_OP(uint8, uint8_t, NUM2UINT, UINT2NUM);
133
- NUM_OP(int16, int16_t, NUM2INT, INT2NUM);
134
- NUM_OP(uint16, uint16_t, NUM2UINT, UINT2NUM);
135
- NUM_OP(int32, int32_t, NUM2INT, INT2NUM);
136
- NUM_OP(uint32, uint32_t, NUM2UINT, UINT2NUM);
137
- NUM_OP(int64, int64_t, NUM2LL, LL2NUM);
138
- NUM_OP(uint64, uint64_t, NUM2ULL, ULL2NUM);
139
- NUM_OP(long, long, NUM2LONG, LONG2NUM);
140
- NUM_OP(ulong, unsigned long, NUM2ULONG, ULONG2NUM);
141
- NUM_OP(float32, float, NUM2DBL, rb_float_new);
142
- NUM_OP(float64, double, NUM2DBL, rb_float_new);
125
+ #define NOSWAP(x) (x)
126
+ #define bswap16(x) (((x) >> 8) & 0xff) | (((x) << 8) & 0xff00);
127
+ static inline int16_t
128
+ SWAPS16(int16_t x)
129
+ {
130
+ return bswap16(x);
131
+ }
132
+
133
+ static inline uint16_t
134
+ SWAPU16(uint16_t x)
135
+ {
136
+ return bswap16(x);
137
+ }
138
+
139
+ #define SWAP16(x) (x)
140
+ #define SWAP32(x) __builtin_bswap32(x)
141
+ #define SWAP64(x) __builtin_bswap64(x)
142
+
143
+ #if LONG_MAX > INT_MAX
144
+ # define SWAPLONG SWAP64
145
+ #else
146
+ # define SWAPLONG SWAP32
147
+ #endif
148
+
149
+ NUM_OP(int8, int8_t, NUM2INT, INT2NUM, NOSWAP);
150
+ NUM_OP(uint8, uint8_t, NUM2UINT, UINT2NUM, NOSWAP);
151
+ NUM_OP(int16, int16_t, NUM2INT, INT2NUM, SWAP16);
152
+ NUM_OP(uint16, uint16_t, NUM2UINT, UINT2NUM, SWAP16);
153
+ NUM_OP(int32, int32_t, NUM2INT, INT2NUM, SWAP32);
154
+ NUM_OP(uint32, uint32_t, NUM2UINT, UINT2NUM, SWAP32);
155
+ NUM_OP(int64, int64_t, NUM2LL, LL2NUM, SWAP64);
156
+ NUM_OP(uint64, uint64_t, NUM2ULL, ULL2NUM, SWAP64);
157
+ NUM_OP(long, long, NUM2LONG, LONG2NUM, SWAPLONG);
158
+ NUM_OP(ulong, unsigned long, NUM2ULONG, ULONG2NUM, SWAPLONG);
159
+ NUM_OP(float32, float, NUM2DBL, rb_float_new, NOSWAP);
160
+ NUM_OP(float64, double, NUM2DBL, rb_float_new, NOSWAP);
143
161
 
144
162
  static inline void*
145
163
  get_pointer_value(VALUE value)
@@ -161,7 +179,7 @@ get_pointer_value(VALUE value)
161
179
  }
162
180
  }
163
181
 
164
- NUM_OP(pointer, void *, get_pointer_value, rbffi_Pointer_NewInstance);
182
+ NUM_OP(pointer, void *, get_pointer_value, rbffi_Pointer_NewInstance, NOSWAP);
165
183
 
166
184
  static VALUE
167
185
  memory_clear(VALUE self)