ffi_wide_char 1.0.2 → 1.1.0
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.
- checksums.yaml +4 -4
- data/README.md +64 -0
- data/lib/ffi_wide_char.rb +36 -55
- data/lib/ffi_wide_char/api.rb +9 -2
- data/lib/ffi_wide_char/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f13487162d031d2b591d6e7ef446edce77c9b4e635499944448a1f374d735240
|
4
|
+
data.tar.gz: 83e493aa9e66d21f8738ed895e2b55b4bcd1cc25ce291440ce9ada8454a340cc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a9d0de60039102974f50dcc2a8648d12a03afe67c0653304cac26217b57e8a067dd7289f00eae86f86cfe09c82148e0fd95dd2ef4dce36474fd8ed8d42a1489a
|
7
|
+
data.tar.gz: 75b9169991423761bdd3ba66119a41e41867798f19fa5696733a57ce7cc157ca83578d4b9b0836617df9312ce6f4d86e3df03fc8c228da17d7f66c53b53c9c1b
|
data/README.md
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
# FfiWideChar [](https://travis-ci.org/nthachus/ffi_wide_char)
|
2
|
+
|
3
|
+
A Ruby gem helper for FFI binding libraries to convert from/to C native `wchar_t` wide-string.
|
4
|
+
|
5
|
+
It provides 2 methods: `read_wide_string` and `to_wide_string` for converting.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'ffi_wide_char'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install ffi_wide_char
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
Example of calling native library functions using `wide-string` type:
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
require 'ffi_wide_char'
|
29
|
+
|
30
|
+
# Unicode Popup Dialog
|
31
|
+
module Win
|
32
|
+
extend FFI::Library
|
33
|
+
|
34
|
+
ffi_lib 'user32'
|
35
|
+
ffi_convention :stdcall
|
36
|
+
|
37
|
+
attach_function :message_box, :MessageBoxW, %i[pointer buffer_in buffer_in int], :int
|
38
|
+
end
|
39
|
+
|
40
|
+
msg = FfiWideChar.to_wide_string('a中Я')
|
41
|
+
Win.message_box(nil, msg, msg, 0)
|
42
|
+
|
43
|
+
# Convert multibyte to wide-string
|
44
|
+
ptr = FFI::MemoryPointer.new(:char, 16)
|
45
|
+
FfiWideChar::LibC.mbstowcs(ptr, '©Ðõ'.encode('filesystem'), 4)
|
46
|
+
|
47
|
+
str = FfiWideChar.read_wide_string ptr
|
48
|
+
puts str.encode('UTF-8')
|
49
|
+
```
|
50
|
+
|
51
|
+
## Development
|
52
|
+
|
53
|
+
After checking out the repo, run `bundle install` to install dependencies. Then, run `bundle exec rake` to run the tests.
|
54
|
+
You can also run `irb -r bundler/setup -r ffi_wide_char` for an interactive prompt that will allow you to experiment.
|
55
|
+
|
56
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
57
|
+
|
58
|
+
## Contributing
|
59
|
+
|
60
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/nthachus/ffi_wide_char.
|
61
|
+
|
62
|
+
## License
|
63
|
+
|
64
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/lib/ffi_wide_char.rb
CHANGED
@@ -1,89 +1,70 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'ffi'
|
4
|
-
|
5
|
-
require 'ffi_wide_char/api'
|
6
3
|
require 'ffi_wide_char/version'
|
4
|
+
require 'ffi_wide_char/api'
|
7
5
|
|
8
6
|
module FfiWideChar
|
9
|
-
class
|
10
|
-
class UnsupportedWCharEncodingError < StandardError; end
|
7
|
+
class Error < StandardError; end
|
11
8
|
|
12
|
-
|
13
|
-
|
14
|
-
"!\x00@\x00\x00
|
15
|
-
"\x00
|
16
|
-
"
|
17
|
-
"\x00\x00\x00!\x00\x00" => 'UTF-32BE'
|
9
|
+
ENCODINGS = {
|
10
|
+
'UTF-16LE' => "!\x00@\x00\x00\x00",
|
11
|
+
'UTF-16BE' => "\x00!\x00@\x00\x00",
|
12
|
+
'UTF-32LE' => "!\x00\x00\x00@\x00",
|
13
|
+
'UTF-32BE' => "\x00\x00\x00!\x00\x00"
|
18
14
|
}.freeze
|
19
15
|
|
20
|
-
W_CHAR_ENC = nil
|
21
|
-
W_CHAR_SIZE = 2
|
22
|
-
W_CHAR_FUNC = :get_uint16
|
23
|
-
|
24
16
|
# All methods in this block are static
|
25
17
|
class << self
|
26
18
|
# Detect `wchar_t` encoding.
|
27
|
-
# @return [String]
|
28
|
-
def
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
19
|
+
# @return [String] Encoding name of the wide-string .
|
20
|
+
def encoding
|
21
|
+
@encoding ||=
|
22
|
+
begin
|
23
|
+
ptr = FFI::MemoryPointer.new(:char, 12)
|
24
|
+
rc = LibC.mbstowcs(ptr, '!@', 3)
|
25
|
+
raise Error, 'Invalid multibyte character' unless rc.is_a?(Integer) && rc >= 0
|
26
|
+
|
27
|
+
str = ptr.get_bytes(0, 6)
|
28
|
+
enc = ENCODINGS.key(str)
|
29
|
+
raise Error, "Unsupported wide-character encoding #{str.inspect}" unless enc
|
30
|
+
|
31
|
+
enc
|
32
|
+
end
|
39
33
|
end
|
40
34
|
|
41
|
-
|
42
|
-
|
35
|
+
alias detect_encoding encoding
|
36
|
+
|
37
|
+
# Look for a null-terminated characters; if found, read up to that null (exclusive)
|
38
|
+
# @param ptr [FFI::Pointer] A wide-string pointer.
|
43
39
|
# @return [String] Decoded wide-string.
|
44
40
|
def read_wide_string(ptr)
|
45
|
-
return nil
|
41
|
+
return nil if !ptr.respond_to?(:null?) || ptr.null?
|
42
|
+
|
43
|
+
@size ||= encoding.include?('32') ? 4 : 2
|
44
|
+
@func ||= @size == 4 ? :get_int32 : :get_int16
|
46
45
|
|
47
46
|
len = get_wide_string_len ptr
|
48
|
-
ptr.get_bytes(0, len).force_encoding(
|
47
|
+
ptr.get_bytes(0, len).force_encoding(encoding)
|
49
48
|
end
|
50
49
|
|
51
50
|
# Convert a Ruby string into a C native wide-string.
|
52
51
|
# @param str [String] A Ruby string.
|
53
52
|
# @return [String] C native wide-string.
|
54
53
|
def to_wide_string(str)
|
55
|
-
str ? str.encode(
|
54
|
+
str ? str.encode(encoding) : str
|
56
55
|
end
|
57
56
|
|
58
57
|
private
|
59
58
|
|
60
|
-
#
|
61
|
-
# @
|
62
|
-
def redefine_consts(enc)
|
63
|
-
[:W_CHAR_ENC, :W_CHAR_SIZE, :W_CHAR_FUNC].each { |name| send :remove_const, name }
|
64
|
-
|
65
|
-
const_set :W_CHAR_ENC, enc
|
66
|
-
const_set :W_CHAR_SIZE, enc.include?('32') ? 4 : 2
|
67
|
-
const_set :W_CHAR_FUNC, W_CHAR_SIZE == 4 ? :get_int32 : :get_uint16
|
68
|
-
|
69
|
-
enc
|
70
|
-
end
|
71
|
-
|
72
|
-
# @param obj [Object]
|
73
|
-
# @param name [Symbol]
|
74
|
-
# @return [Object]
|
75
|
-
def get_object_attr(obj, name)
|
76
|
-
obj.respond_to?(name) ? obj.send(name) : nil
|
77
|
-
end
|
78
|
-
|
79
|
-
# @param ptr [Pointer]
|
59
|
+
# Detect wide-string length in bytes
|
60
|
+
# @param ptr [FFI::Pointer]
|
80
61
|
# @return [Integer]
|
81
62
|
def get_wide_string_len(ptr)
|
82
|
-
sz =
|
83
|
-
sz -=
|
63
|
+
sz = ptr.size
|
64
|
+
sz -= @size if sz
|
84
65
|
|
85
66
|
len = 0
|
86
|
-
len +=
|
67
|
+
len += @size while (!sz || len < sz) && ptr.send(@func, len) != 0
|
87
68
|
|
88
69
|
len
|
89
70
|
end
|
data/lib/ffi_wide_char/api.rb
CHANGED
@@ -1,12 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'ffi'
|
4
|
+
|
3
5
|
module FfiWideChar
|
4
6
|
module LibC
|
5
7
|
extend FFI::Library
|
6
8
|
ffi_lib FFI::Library::LIBC
|
7
9
|
|
8
|
-
#
|
9
|
-
#
|
10
|
+
# @!scope class
|
11
|
+
# @!method mbstowcs(dest, src, size)
|
12
|
+
# Converts a string of multibyte characters to a wide character array
|
13
|
+
# @param dest [FFI::Pointer] of wchar_t*
|
14
|
+
# @param src [String]
|
15
|
+
# @param size [Integer] Max number of :wchar_t characters to write to dest
|
16
|
+
# @return [Integer] Number of :wchar_t written to dest (w/o null-terminated), or -1 if error
|
10
17
|
attach_function :mbstowcs, [:pointer, :string, :size_t], :size_t
|
11
18
|
end
|
12
19
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ffi_wide_char
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thach Nguyen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date:
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ffi
|
@@ -88,6 +88,7 @@ extensions: []
|
|
88
88
|
extra_rdoc_files: []
|
89
89
|
files:
|
90
90
|
- LICENSE.txt
|
91
|
+
- README.md
|
91
92
|
- lib/ffi_wide_char/api.rb
|
92
93
|
- lib/ffi_wide_char/version.rb
|
93
94
|
- lib/ffi_wide_char.rb
|
@@ -110,8 +111,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
110
111
|
- !ruby/object:Gem::Version
|
111
112
|
version: '0'
|
112
113
|
requirements: []
|
113
|
-
|
114
|
-
rubygems_version: 2.7.6.2
|
114
|
+
rubygems_version: 3.0.3
|
115
115
|
signing_key:
|
116
116
|
specification_version: 4
|
117
117
|
summary: Provides methods to convert from/to FFI wide-string.
|