ffi-chm 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gemtest ADDED
File without changes
data/README.txt ADDED
@@ -0,0 +1,62 @@
1
+ = ffi-chm
2
+
3
+ * http://github.com/nanki/ffi-chm
4
+
5
+ == DESCRIPTION:
6
+
7
+ Ruby bindings for the libchm via FFI.
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ * Provides basic access to the CHM files.
12
+ * Currently developed on MRI 1.8 / 1.9
13
+
14
+ == SYNOPSIS:
15
+
16
+ FFI::Chm::ChmFile.new("reference-manual.chm") do |chm|
17
+ chm.enumerate(:normal, :files).map{|ui| ui[:path]}
18
+ end
19
+
20
+ == REQUIREMENTS:
21
+
22
+ * Ruby
23
+ * libffi
24
+ * libchm
25
+
26
+ == INSTALL:
27
+
28
+ $ gem install ffi-chm
29
+
30
+ == DEVELOPERS:
31
+
32
+ After checking out the source, run:
33
+
34
+ $ rake newb
35
+
36
+ This task will install any missing dependencies, run the tests/specs,
37
+ and generate the RDoc.
38
+
39
+ == LICENSE:
40
+
41
+ (The MIT License)
42
+
43
+ Copyright (c) 2011 NANKI Haruo
44
+
45
+ Permission is hereby granted, free of charge, to any person obtaining
46
+ a copy of this software and associated documentation files (the
47
+ 'Software'), to deal in the Software without restriction, including
48
+ without limitation the rights to use, copy, modify, merge, publish,
49
+ distribute, sublicense, and/or sell copies of the Software, and to
50
+ permit persons to whom the Software is furnished to do so, subject to
51
+ the following conditions:
52
+
53
+ The above copyright notice and this permission notice shall be
54
+ included in all copies or substantial portions of the Software.
55
+
56
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
57
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
58
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
59
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
60
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
61
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
62
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,22 @@
1
+ require 'ffi'
2
+
3
+ module FFI::Chm::API
4
+ extend FFI::Library
5
+
6
+ ffi_lib('chm')
7
+
8
+ # proc {|handle, unitinfo, userdata| ... }
9
+ callback :enumerator, [:pointer, :pointer, :pointer], :int
10
+
11
+ prototypes = [
12
+ [:chm_open, [:string], :pointer],
13
+ [:chm_close, [:pointer], :void],
14
+ [:chm_set_param, [:pointer, :int, :int], :void],
15
+ [:chm_resolve_object, [:pointer, :string, :buffer_out], :int],
16
+ [:chm_retrieve_object, [:pointer, :pointer, :buffer_out, :uint64, :int64], :int64],
17
+ [:chm_enumerate, [:pointer, :int, :enumerator, :pointer], :int],
18
+ [:chm_enumerate_dir, [:pointer, :string, :int, :enumerator, :pointer], :int]
19
+ ]
20
+
21
+ prototypes.each {|func| attach_function(*func)}
22
+ end
@@ -0,0 +1,33 @@
1
+ module FFI::Chm::Const
2
+ MAX_PATHLEN = 512
3
+
4
+ UNCOMPRESSED = 0
5
+ COMPRESSED = 1
6
+
7
+ PARAM_MAX_BLOCKS_CACHED = 0
8
+
9
+ RESOLVE_SUCCESS = 0
10
+ RESOLVE_FAILURE = 1
11
+
12
+ ENUMERATE_NORMAL = 1
13
+ ENUMERATE_META = 2
14
+ ENUMERATE_SPECIAL = 4
15
+
16
+ ENUMERATE_FILES = 8
17
+ ENUMERATE_DIRS = 16
18
+
19
+ ENUMERATE_ALL = 31
20
+
21
+ ENUMERATE_FLAGS = Hash[
22
+ :normal, ENUMERATE_NORMAL,
23
+ :meta, ENUMERATE_META,
24
+ :special, ENUMERATE_SPECIAL,
25
+ :files, ENUMERATE_FILES,
26
+ :dirs, ENUMERATE_DIRS,
27
+ :all, ENUMERATE_ALL
28
+ ]
29
+
30
+ ENUMERATOR_FAILURE = 0
31
+ ENUMERATOR_CONTINUE = 1
32
+ ENUMERATOR_SUCCESS = 2
33
+ end
data/lib/ffi-chm.rb ADDED
@@ -0,0 +1,132 @@
1
+ module FFI
2
+ module Chm
3
+ VERSION = '0.1.0'
4
+ end
5
+ end
6
+
7
+ require 'ffi-chm/const'
8
+ require 'ffi-chm/api'
9
+
10
+ module FFI::Chm
11
+ include API
12
+ include Const
13
+
14
+ class ChmError < StandardError;end
15
+ class ResolveError < ChmError;end
16
+ class RetrieveError < ChmError;end
17
+
18
+ class ChmFile
19
+ def initialize(fn)
20
+ @h = API.chm_open fn
21
+ raise ChmError, "Not exists?" if @h.null?
22
+ if block_given?
23
+ begin
24
+ yield self
25
+ ensure
26
+ self.close
27
+ end
28
+ end
29
+ end
30
+
31
+ def close
32
+ API.chm_close @h unless @h.null?
33
+ end
34
+
35
+ def set_param(param, value)
36
+ API.chm_set_param @h, param, value
37
+ end
38
+
39
+ def resolve_object(name)
40
+ ui = UnitInfo.new
41
+ case API.chm_resolve_object @h, name, ui
42
+ when Const::RESOLVE_SUCCESS
43
+ ui
44
+ when Const::RESOLVE_FAILURE
45
+ raise ResolveError
46
+ end
47
+ end
48
+
49
+ def retrieve_object(ui)
50
+ if UnitInfo === ui
51
+ buf = FFI::Buffer.new ui[:length]
52
+ API.chm_retrieve_object @h, ui, buf, 0, ui[:length]
53
+ buf.read_bytes buf.size
54
+ else
55
+ retrieve_object resolve_object(ui)
56
+ end
57
+ rescue ResolveError
58
+ raise RetrieveError, ui
59
+ end
60
+
61
+ require 'enumerator'
62
+ def enumerate(*what, &block)
63
+ if block_given?
64
+ API.chm_enumerate @h, to_flags(what), enum_func(&block), nil
65
+ self
66
+ else
67
+ (Enumerable::Enumerator rescue Enumerator).new self, :enumerate, to_flags(what)
68
+ end
69
+ end
70
+
71
+ def enumerate_dir(prefix, *what, &block)
72
+ if block_given?
73
+ API.chm_enumerate_dir @h, prefix, to_flags(what), enum_func(&block), nil
74
+ self
75
+ else
76
+ (Enumerable::Enumerator rescue Enumerator).new self, :enumerate_dir, prefix, to_flags(what)
77
+ end
78
+ end
79
+
80
+ private
81
+ def enum_func(&block)
82
+ lambda do |h, ui, _|
83
+ begin
84
+ if block.call(UnitInfo.new(ui).clone) == :break
85
+ Const::ENUMERATOR_SUCCESS
86
+ else
87
+ Const::ENUMERATOR_CONTINUE
88
+ end
89
+ rescue
90
+ Const::ENUMERATOR_FAILURE
91
+ end
92
+ end
93
+ end
94
+
95
+ def to_flags(what)
96
+ if what.size == 1 && Integer === what.first
97
+ what.first
98
+ else
99
+ what.inject(0) do |r, sym|
100
+ r | (Const::ENUMERATE_FLAGS[sym] || 0)
101
+ end
102
+ end
103
+ end
104
+ end
105
+
106
+ class UnitInfo < FFI::Struct
107
+ layout :start, :uint64,
108
+ :length, :uint64,
109
+ :space, :int,
110
+ :flags, :int,
111
+ :path, [:char, Const::MAX_PATHLEN + 1]
112
+
113
+ def dir?
114
+ flag? :dirs
115
+ end
116
+
117
+ def file?
118
+ flag? :files
119
+ end
120
+
121
+ %w(normal special meta).each do |name|
122
+ define_method("#{name}?") do
123
+ flag? name.intern
124
+ end
125
+ end
126
+
127
+ private
128
+ def flag?(flag)
129
+ !!(self[:flags] & Const::ENUMERATE_FLAGS[flag]).nonzero?
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,8 @@
1
+ require "test/unit"
2
+ require "ffi-chm"
3
+
4
+ class TestFFIChm < Test::Unit::TestCase
5
+ def test_ffi_chm
6
+ assert true
7
+ end
8
+ end
metadata ADDED
@@ -0,0 +1,102 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ffi-chm
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - nanki
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-07-28 00:00:00 +09:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: ffi
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: hoe
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ hash: 23
44
+ segments:
45
+ - 2
46
+ - 10
47
+ version: "2.10"
48
+ type: :development
49
+ version_requirements: *id002
50
+ description: Ruby bindings for the libchm via FFI.
51
+ email:
52
+ - nanki@dotswitch.net
53
+ executables: []
54
+
55
+ extensions: []
56
+
57
+ extra_rdoc_files:
58
+ - README.txt
59
+ files:
60
+ - README.txt
61
+ - lib/ffi-chm.rb
62
+ - lib/ffi-chm/api.rb
63
+ - lib/ffi-chm/const.rb
64
+ - test/test_ffi_chm.rb
65
+ - .gemtest
66
+ has_rdoc: true
67
+ homepage: http://github.com/nanki/ffi-chm
68
+ licenses: []
69
+
70
+ post_install_message:
71
+ rdoc_options:
72
+ - --main
73
+ - README.txt
74
+ require_paths:
75
+ - lib
76
+ required_ruby_version: !ruby/object:Gem::Requirement
77
+ none: false
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ hash: 3
82
+ segments:
83
+ - 0
84
+ version: "0"
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ hash: 3
91
+ segments:
92
+ - 0
93
+ version: "0"
94
+ requirements: []
95
+
96
+ rubyforge_project: ffi-chm
97
+ rubygems_version: 1.6.2
98
+ signing_key:
99
+ specification_version: 3
100
+ summary: Ruby bindings for the libchm via FFI.
101
+ test_files:
102
+ - test/test_ffi_chm.rb