ffi-icu 0.0.9 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/ffi-icu.rb +2 -0
- data/lib/ffi-icu/lib.rb +63 -2
- data/lib/ffi-icu/lib/util.rb +47 -0
- data/lib/ffi-icu/locale.rb +224 -0
- data/lib/ffi-icu/uchar.rb +2 -2
- data/lib/ffi-icu/version.rb +1 -1
- data/spec/collation_spec.rb +1 -1
- data/spec/lib_spec.rb +47 -0
- data/spec/locale_spec.rb +250 -0
- data/spec/uchar_spec.rb +31 -0
- metadata +9 -1
data/lib/ffi-icu.rb
CHANGED
@@ -31,9 +31,11 @@ end
|
|
31
31
|
|
32
32
|
require "ffi-icu/core_ext/string"
|
33
33
|
require "ffi-icu/lib"
|
34
|
+
require "ffi-icu/lib/util"
|
34
35
|
require "ffi-icu/uchar"
|
35
36
|
require "ffi-icu/chardet"
|
36
37
|
require "ffi-icu/collation"
|
38
|
+
require "ffi-icu/locale"
|
37
39
|
require "ffi-icu/transliteration"
|
38
40
|
require "ffi-icu/normalization"
|
39
41
|
require "ffi-icu/break_iterator"
|
data/lib/ffi-icu/lib.rb
CHANGED
@@ -15,7 +15,13 @@ module ICU
|
|
15
15
|
elsif FFI::Platform::IS_WINDOWS
|
16
16
|
ENV['PATH'].split(File::PATH_SEPARATOR)
|
17
17
|
else
|
18
|
-
[
|
18
|
+
[
|
19
|
+
'/usr/local/{lib64,lib}',
|
20
|
+
'/opt/local/{lib64,lib}',
|
21
|
+
'/usr/{lib64,lib}',
|
22
|
+
'/usr/lib/x86_64-linux-gnu', # for Debian Multiarch http://wiki.debian.org/Multiarch
|
23
|
+
'/usr/lib/i386-linux-gnu', # for Debian Multiarch
|
24
|
+
]
|
19
25
|
end
|
20
26
|
end
|
21
27
|
end
|
@@ -42,7 +48,7 @@ module ICU
|
|
42
48
|
lib_names.compact! if lib_names
|
43
49
|
|
44
50
|
if not lib_names or lib_names.length == 0
|
45
|
-
raise LoadError, "Could not find ICU on #{ICU.platform.inspect},
|
51
|
+
raise LoadError, "Could not find ICU on #{ICU.platform.inspect}. Patches welcome, or you can add the containing directory yourself: #{self}.search_paths << '/path/to/lib'"
|
46
52
|
end
|
47
53
|
|
48
54
|
# And now try to load the library
|
@@ -123,6 +129,14 @@ module ICU
|
|
123
129
|
ret
|
124
130
|
end
|
125
131
|
|
132
|
+
def self.cldr_version
|
133
|
+
result = FFI::MemoryPointer.new(:char, 64)
|
134
|
+
version_info = FFI::MemoryPointer.new(:uint8, 4)
|
135
|
+
check_error { |status| ulocdata_getCLDRVersion(version_info, status) }
|
136
|
+
u_versionToString(version_info, result)
|
137
|
+
result.read_string_to_null
|
138
|
+
end
|
139
|
+
|
126
140
|
def self.enum_ptr_to_array(enum_ptr)
|
127
141
|
length = check_error do |status|
|
128
142
|
uenum_count(enum_ptr, status)
|
@@ -150,6 +164,53 @@ module ICU
|
|
150
164
|
attach_function :uenum_next, "uenum_next#{suffix}", [:pointer, :pointer, :pointer], :string
|
151
165
|
attach_function :u_charsToUChars, "u_charsToUChars#{suffix}", [:string, :pointer, :int32_t], :void
|
152
166
|
attach_function :u_UCharsToChars, "u_UCharsToChars#{suffix}", [:pointer, :string, :int32_t], :void
|
167
|
+
attach_function :u_versionToString, "u_versionToString#{suffix}", [:pointer, :pointer], :void
|
168
|
+
|
169
|
+
#
|
170
|
+
# Locale
|
171
|
+
#
|
172
|
+
# http://icu-project.org/apiref/icu4c/uloc_8h.html
|
173
|
+
#
|
174
|
+
|
175
|
+
enum :layout_type, [:ltr, :rtl, :ttb, :btt, :unknown]
|
176
|
+
|
177
|
+
attach_function :uloc_addLikelySubtags, "uloc_addLikelySubtags#{suffix}", [:string, :pointer, :int32_t, :pointer], :int32_t
|
178
|
+
attach_function :uloc_canonicalize, "uloc_canonicalize#{suffix}", [:string, :pointer, :int32_t, :pointer], :int32_t
|
179
|
+
attach_function :uloc_countAvailable, "uloc_countAvailable#{suffix}", [], :int32_t
|
180
|
+
attach_function :uloc_forLanguageTag, "uloc_forLanguageTag#{suffix}", [:string, :pointer, :int32_t, :pointer, :pointer], :int32_t
|
181
|
+
attach_function :uloc_getAvailable, "uloc_getAvailable#{suffix}", [:int32_t], :string
|
182
|
+
attach_function :uloc_getBaseName, "uloc_getBaseName#{suffix}", [:string, :pointer, :int32_t, :pointer], :int32_t
|
183
|
+
attach_function :uloc_getCountry, "uloc_getCountry#{suffix}", [:string, :pointer, :int32_t, :pointer], :int32_t
|
184
|
+
attach_function :uloc_getDefault, "uloc_getDefault#{suffix}", [], :string
|
185
|
+
attach_function :uloc_getISO3Country, "uloc_getISO3Country#{suffix}", [:string], :string
|
186
|
+
attach_function :uloc_getISO3Language, "uloc_getISO3Language#{suffix}", [:string], :string
|
187
|
+
attach_function :uloc_getISOCountries, "uloc_getISOCountries#{suffix}", [], :pointer
|
188
|
+
attach_function :uloc_getISOLanguages, "uloc_getISOLanguages#{suffix}", [], :pointer
|
189
|
+
attach_function :uloc_getKeywordValue, "uloc_getKeywordValue#{suffix}", [:string, :string, :pointer, :int32_t, :pointer], :int32_t
|
190
|
+
attach_function :uloc_getLanguage, "uloc_getLanguage#{suffix}", [:string, :pointer, :int32_t, :pointer], :int32_t
|
191
|
+
attach_function :uloc_getLocaleForLCID, "uloc_getLocaleForLCID#{suffix}", [:uint32, :pointer, :int32_t, :pointer], :int32_t
|
192
|
+
attach_function :uloc_getLCID, "uloc_getLCID#{suffix}", [:string], :uint32
|
193
|
+
attach_function :uloc_getName, "uloc_getName#{suffix}", [:string, :pointer, :int32_t, :pointer], :int32_t
|
194
|
+
attach_function :uloc_getParent, "uloc_getParent#{suffix}", [:string, :pointer, :int32_t, :pointer], :int32_t
|
195
|
+
attach_function :uloc_getScript, "uloc_getScript#{suffix}", [:string, :pointer, :int32_t, :pointer], :int32_t
|
196
|
+
attach_function :uloc_getVariant, "uloc_getVariant#{suffix}", [:string, :pointer, :int32_t, :pointer], :int32_t
|
197
|
+
attach_function :uloc_minimizeSubtags, "uloc_minimizeSubtags#{suffix}", [:string, :pointer, :int32_t, :pointer], :int32_t
|
198
|
+
attach_function :uloc_openKeywords, "uloc_openKeywords#{suffix}", [:string, :pointer], :pointer
|
199
|
+
attach_function :uloc_setDefault, "uloc_setDefault#{suffix}", [:string, :pointer], :void
|
200
|
+
attach_function :uloc_setKeywordValue, "uloc_setKeywordValue#{suffix}", [:string, :string, :pointer, :int32_t, :pointer], :int32_t
|
201
|
+
attach_function :uloc_toLanguageTag, "uloc_toLanguageTag#{suffix}", [:string, :pointer, :int32_t, :int8_t, :pointer], :int32_t
|
202
|
+
|
203
|
+
attach_function :uloc_getCharacterOrientation, "uloc_getCharacterOrientation#{suffix}", [:string, :pointer], :layout_type
|
204
|
+
attach_function :uloc_getDisplayCountry, "uloc_getDisplayCountry#{suffix}", [:string, :string, :pointer, :int32_t, :pointer], :int32_t
|
205
|
+
attach_function :uloc_getDisplayKeyword, "uloc_getDisplayKeyword#{suffix}", [:string, :string, :pointer, :int32_t, :pointer], :int32_t
|
206
|
+
attach_function :uloc_getDisplayKeywordValue, "uloc_getDisplayKeywordValue#{suffix}", [:string, :string, :string, :pointer, :int32_t, :pointer], :int32_t
|
207
|
+
attach_function :uloc_getDisplayLanguage, "uloc_getDisplayLanguage#{suffix}", [:string, :string, :pointer, :int32_t, :pointer], :int32_t
|
208
|
+
attach_function :uloc_getDisplayName, "uloc_getDisplayName#{suffix}", [:string, :string, :pointer, :int32_t, :pointer], :int32_t
|
209
|
+
attach_function :uloc_getDisplayScript, "uloc_getDisplayScript#{suffix}", [:string, :string, :pointer, :int32_t, :pointer], :int32_t
|
210
|
+
attach_function :uloc_getDisplayVariant, "uloc_getDisplayVariant#{suffix}", [:string, :string, :pointer, :int32_t, :pointer], :int32_t
|
211
|
+
attach_function :uloc_getLineOrientation, "uloc_getLineOrientation#{suffix}", [:string, :pointer], :layout_type
|
212
|
+
|
213
|
+
attach_function :ulocdata_getCLDRVersion, "ulocdata_getCLDRVersion#{suffix}", [:pointer, :pointer], :void
|
153
214
|
|
154
215
|
# CharDet
|
155
216
|
#
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module ICU
|
2
|
+
module Lib
|
3
|
+
module Util
|
4
|
+
def self.read_null_terminated_array_of_strings(pointer)
|
5
|
+
offset = 0
|
6
|
+
result = []
|
7
|
+
|
8
|
+
while (ptr = pointer.get_pointer(offset)) != FFI::Pointer::NULL do
|
9
|
+
result << ptr.read_string
|
10
|
+
offset += FFI::Pointer.size
|
11
|
+
end
|
12
|
+
|
13
|
+
result
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.read_string_buffer(length)
|
17
|
+
attempts = 0
|
18
|
+
|
19
|
+
begin
|
20
|
+
result = FFI::MemoryPointer.new(:char, length)
|
21
|
+
Lib.check_error { |status| length = yield result, status }
|
22
|
+
rescue BufferOverflowError
|
23
|
+
attempts += 1
|
24
|
+
retry if attempts < 2
|
25
|
+
raise BufferOverflowError, "needed: #{length}"
|
26
|
+
end
|
27
|
+
|
28
|
+
result.read_string(length)
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.read_uchar_buffer(length)
|
32
|
+
attempts = 0
|
33
|
+
|
34
|
+
begin
|
35
|
+
result = UCharPointer.new(length)
|
36
|
+
Lib.check_error { |status| length = yield result, status }
|
37
|
+
rescue BufferOverflowError
|
38
|
+
attempts += 1
|
39
|
+
retry if attempts < 2
|
40
|
+
raise BufferOverflowError, "needed: #{length}"
|
41
|
+
end
|
42
|
+
|
43
|
+
result.string(length)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,224 @@
|
|
1
|
+
module ICU
|
2
|
+
class Locale
|
3
|
+
class << self
|
4
|
+
def available
|
5
|
+
(0...Lib.uloc_countAvailable).map do |idx|
|
6
|
+
Locale.new(Lib.uloc_getAvailable(idx))
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def default
|
11
|
+
Locale.new(Lib.uloc_getDefault)
|
12
|
+
end
|
13
|
+
|
14
|
+
def default=(locale)
|
15
|
+
Lib.check_error { |status| Lib.uloc_setDefault(locale.to_s, status) }
|
16
|
+
end
|
17
|
+
|
18
|
+
def for_language_tag(tag)
|
19
|
+
result = Lib::Util.read_string_buffer(64) do |buffer, status|
|
20
|
+
Lib.uloc_forLanguageTag(tag, buffer, buffer.size, nil, status)
|
21
|
+
end
|
22
|
+
|
23
|
+
Locale.new(result)
|
24
|
+
end
|
25
|
+
|
26
|
+
def for_lcid(id)
|
27
|
+
result = Lib::Util.read_string_buffer(64) do |buffer, status|
|
28
|
+
Lib.uloc_getLocaleForLCID(id, buffer, buffer.size, status)
|
29
|
+
end
|
30
|
+
|
31
|
+
Locale.new(result)
|
32
|
+
end
|
33
|
+
|
34
|
+
def iso_countries
|
35
|
+
Lib::Util.read_null_terminated_array_of_strings(Lib.uloc_getISOCountries)
|
36
|
+
end
|
37
|
+
|
38
|
+
def iso_languages
|
39
|
+
Lib::Util.read_null_terminated_array_of_strings(Lib.uloc_getISOLanguages)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
attr_reader :id
|
44
|
+
|
45
|
+
def initialize(id)
|
46
|
+
@id = id.to_s
|
47
|
+
end
|
48
|
+
|
49
|
+
def ==(other)
|
50
|
+
other.is_a?(self.class) && other.id == self.id
|
51
|
+
end
|
52
|
+
|
53
|
+
def base_name
|
54
|
+
Lib::Util.read_string_buffer(64) do |buffer, status|
|
55
|
+
Lib.uloc_getBaseName(@id, buffer, buffer.size, status)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def canonical
|
60
|
+
Lib::Util.read_string_buffer(64) do |buffer, status|
|
61
|
+
Lib.uloc_canonicalize(@id, buffer, buffer.size, status)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def character_orientation
|
66
|
+
Lib.check_error { |status| Lib.uloc_getCharacterOrientation(@id, status) }
|
67
|
+
end
|
68
|
+
|
69
|
+
def country
|
70
|
+
Lib::Util.read_string_buffer(64) do |buffer, status|
|
71
|
+
Lib.uloc_getCountry(@id, buffer, buffer.size, status)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def display_country(locale = nil)
|
76
|
+
locale = locale.to_s unless locale.nil?
|
77
|
+
|
78
|
+
Lib::Util.read_uchar_buffer(64) do |buffer, status|
|
79
|
+
Lib.uloc_getDisplayCountry(@id, locale, buffer, buffer.size, status)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def display_language(locale = nil)
|
84
|
+
locale = locale.to_s unless locale.nil?
|
85
|
+
|
86
|
+
Lib::Util.read_uchar_buffer(64) do |buffer, status|
|
87
|
+
Lib.uloc_getDisplayLanguage(@id, locale, buffer, buffer.size, status)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def display_name(locale = nil)
|
92
|
+
locale = locale.to_s unless locale.nil?
|
93
|
+
|
94
|
+
Lib::Util.read_uchar_buffer(64) do |buffer, status|
|
95
|
+
Lib.uloc_getDisplayName(@id, locale, buffer, buffer.size, status)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def display_script(locale = nil)
|
100
|
+
locale = locale.to_s unless locale.nil?
|
101
|
+
|
102
|
+
Lib::Util.read_uchar_buffer(64) do |buffer, status|
|
103
|
+
Lib.uloc_getDisplayScript(@id, locale, buffer, buffer.size, status)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def display_variant(locale = nil)
|
108
|
+
locale = locale.to_s unless locale.nil?
|
109
|
+
|
110
|
+
Lib::Util.read_uchar_buffer(64) do |buffer, status|
|
111
|
+
Lib.uloc_getDisplayVariant(@id, locale, buffer, buffer.size, status)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def iso_country
|
116
|
+
Lib.uloc_getISO3Country(@id)
|
117
|
+
end
|
118
|
+
|
119
|
+
def iso_language
|
120
|
+
Lib.uloc_getISO3Language(@id)
|
121
|
+
end
|
122
|
+
|
123
|
+
def keyword(keyword)
|
124
|
+
Lib::Util.read_string_buffer(64) do |buffer, status|
|
125
|
+
Lib.uloc_getKeywordValue(@id, keyword.to_s, buffer, buffer.size, status)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def keywords
|
130
|
+
enum_ptr = Lib.check_error { |status| Lib.uloc_openKeywords(@id, status) }
|
131
|
+
|
132
|
+
begin
|
133
|
+
Lib.enum_ptr_to_array(enum_ptr)
|
134
|
+
ensure
|
135
|
+
Lib.uenum_close(enum_ptr)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def language
|
140
|
+
Lib::Util.read_string_buffer(64) do |buffer, status|
|
141
|
+
Lib.uloc_getLanguage(@id, buffer, buffer.size, status)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def lcid
|
146
|
+
Lib.uloc_getLCID(@id)
|
147
|
+
end
|
148
|
+
|
149
|
+
def line_orientation
|
150
|
+
Lib.check_error { |status| Lib.uloc_getLineOrientation(@id, status) }
|
151
|
+
end
|
152
|
+
|
153
|
+
def name
|
154
|
+
Lib::Util.read_string_buffer(64) do |buffer, status|
|
155
|
+
Lib.uloc_getName(@id, buffer, buffer.size, status)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def parent
|
160
|
+
Lib::Util.read_string_buffer(64) do |buffer, status|
|
161
|
+
Lib.uloc_getParent(@id, buffer, buffer.size, status)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def script
|
166
|
+
Lib::Util.read_string_buffer(64) do |buffer, status|
|
167
|
+
Lib.uloc_getScript(@id, buffer, buffer.size, status)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def to_language_tag(strict = false)
|
172
|
+
Lib::Util.read_string_buffer(64) do |buffer, status|
|
173
|
+
Lib.uloc_toLanguageTag(@id, buffer, buffer.size, strict ? 1 : 0, status)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
alias_method :to_s, :id
|
178
|
+
|
179
|
+
def variant
|
180
|
+
Lib::Util.read_string_buffer(64) do |buffer, status|
|
181
|
+
Lib.uloc_getVariant(@id, buffer, buffer.size, status)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def with_keyword(keyword, value)
|
186
|
+
keyword = keyword.to_s
|
187
|
+
length = @id.length + keyword.length + 64
|
188
|
+
|
189
|
+
unless value.nil?
|
190
|
+
value = value.to_s
|
191
|
+
length += value.length
|
192
|
+
end
|
193
|
+
|
194
|
+
result = Lib::Util.read_string_buffer(length) do |buffer, status|
|
195
|
+
buffer.write_string(@id)
|
196
|
+
Lib.uloc_setKeywordValue(keyword, value, buffer, buffer.size, status)
|
197
|
+
end
|
198
|
+
|
199
|
+
Locale.new(result)
|
200
|
+
end
|
201
|
+
|
202
|
+
def with_keywords(hash)
|
203
|
+
hash.reduce(self) do |locale, (keyword, value)|
|
204
|
+
locale.with_keyword(keyword, value)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
def with_likely_subtags
|
209
|
+
result = Lib::Util.read_string_buffer(64) do |buffer, status|
|
210
|
+
Lib.uloc_addLikelySubtags(@id, buffer, buffer.size, status)
|
211
|
+
end
|
212
|
+
|
213
|
+
Locale.new(result)
|
214
|
+
end
|
215
|
+
|
216
|
+
def with_minimized_subtags
|
217
|
+
result = Lib::Util.read_string_buffer(64) do |buffer, status|
|
218
|
+
Lib.uloc_minimizeSubtags(@id, buffer, buffer.size, status)
|
219
|
+
end
|
220
|
+
|
221
|
+
Locale.new(result)
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
data/lib/ffi-icu/uchar.rb
CHANGED
@@ -9,7 +9,7 @@ module ICU
|
|
9
9
|
bytes = str.unpack("U*")
|
10
10
|
|
11
11
|
ptr = new bytes.size
|
12
|
-
ptr.
|
12
|
+
ptr.write_array_of_uint16 bytes
|
13
13
|
|
14
14
|
ptr
|
15
15
|
end
|
@@ -29,7 +29,7 @@ module ICU
|
|
29
29
|
def string(length = nil)
|
30
30
|
length ||= size / TYPE_SIZE
|
31
31
|
|
32
|
-
wstring =
|
32
|
+
wstring = read_array_of_uint16(length)
|
33
33
|
wstring.pack("U*")
|
34
34
|
end
|
35
35
|
|
data/lib/ffi-icu/version.rb
CHANGED
data/spec/collation_spec.rb
CHANGED
@@ -36,7 +36,7 @@ module ICU
|
|
36
36
|
it "should compare two strings" do
|
37
37
|
collator.compare("blåbærsyltetøy", "blah").should == 1
|
38
38
|
collator.compare("blah", "blah").should == 0
|
39
|
-
collator.compare("
|
39
|
+
collator.compare("ba", "bl").should == -1
|
40
40
|
end
|
41
41
|
|
42
42
|
it "should know if a string is greater than another" do
|
data/spec/lib_spec.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
module ICU
|
6
|
+
describe Lib do
|
7
|
+
describe 'error checking' do
|
8
|
+
let(:return_value) { double }
|
9
|
+
|
10
|
+
context 'upon success' do
|
11
|
+
it 'returns the block result' do
|
12
|
+
Lib.check_error { |status| return_value }.should == return_value
|
13
|
+
Lib.check_error { |status| status.write_int(0); return_value }.should == return_value
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'upon failure' do
|
18
|
+
it 'raises an error' do
|
19
|
+
expect { Lib.check_error { |status| status.write_int(1) } }.to raise_error ICU::Error, /U_.*_ERROR/
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'upon warning' do
|
24
|
+
before(:each) { @verbose = $VERBOSE }
|
25
|
+
after(:each) { $VERBOSE = @verbose }
|
26
|
+
|
27
|
+
context 'when warnings are enabled' do
|
28
|
+
before(:each) { $VERBOSE = true }
|
29
|
+
|
30
|
+
it 'prints to STDERR and returns the block result' do
|
31
|
+
$stderr.should_receive(:puts) { |message| message.should match /U_.*_WARNING/ }
|
32
|
+
Lib.check_error { |status| status.write_int(-127); return_value }.should == return_value
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'when warnings are disabled' do
|
37
|
+
before(:each) { $VERBOSE = false }
|
38
|
+
|
39
|
+
it 'returns the block result' do
|
40
|
+
$stderr.should_not_receive(:puts)
|
41
|
+
Lib.check_error { |status| status.write_int(-127); return_value }.should == return_value
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/spec/locale_spec.rb
ADDED
@@ -0,0 +1,250 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
module ICU
|
6
|
+
describe Locale do
|
7
|
+
describe 'the available locales' do
|
8
|
+
subject { Locale.available }
|
9
|
+
|
10
|
+
it { should be_an Array }
|
11
|
+
it { should_not be_empty }
|
12
|
+
its(:first) { should be_a Locale }
|
13
|
+
end
|
14
|
+
|
15
|
+
describe 'the available ISO 639 country codes' do
|
16
|
+
subject { Locale.iso_countries }
|
17
|
+
|
18
|
+
it { should be_an Array }
|
19
|
+
it { should_not be_empty }
|
20
|
+
its(:first) { should be_a String }
|
21
|
+
end
|
22
|
+
|
23
|
+
describe 'the available ISO 639 language codes' do
|
24
|
+
subject { Locale.iso_languages }
|
25
|
+
|
26
|
+
it { should be_an Array }
|
27
|
+
it { should_not be_empty }
|
28
|
+
its(:first) { should be_a String }
|
29
|
+
end
|
30
|
+
|
31
|
+
describe 'the default' do
|
32
|
+
subject { Locale.default }
|
33
|
+
|
34
|
+
let(:locale) do
|
35
|
+
locales = Locale.available
|
36
|
+
locales.delete(Locale.default)
|
37
|
+
locales.respond_to?(:sample) ? locales.sample : locales.choice
|
38
|
+
end
|
39
|
+
|
40
|
+
it { should be_a Locale }
|
41
|
+
|
42
|
+
it 'can be assigned using Locale' do
|
43
|
+
(Locale.default = locale).should == locale
|
44
|
+
Locale.default.should == locale
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'can be assigned using string' do
|
48
|
+
string = locale.to_s
|
49
|
+
|
50
|
+
(Locale.default = string).should == string
|
51
|
+
Locale.default.should == Locale.new(string)
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'can be assigned using symbol' do
|
55
|
+
symbol = locale.to_s.to_sym
|
56
|
+
|
57
|
+
(Locale.default = symbol).should == symbol
|
58
|
+
Locale.default.should == Locale.new(symbol)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe 'BCP 47 language tags' do
|
63
|
+
it 'converts a language tag to a locale' do
|
64
|
+
Locale.for_language_tag('en-us').should == Locale.new('en_US')
|
65
|
+
Locale.for_language_tag('nan-Hant-tw').should == Locale.new('nan_Hant_TW')
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'returns a language tag for a locale' do
|
69
|
+
if Gem::Version.new(Lib.cldr_version) < Gem::Version.new('1.8')
|
70
|
+
Locale.new('en_US').to_language_tag.should == 'en-us'
|
71
|
+
Locale.new('zh_TW').to_language_tag.should == 'zh-tw'
|
72
|
+
Locale.new('zh_Hans_CH_PINYIN').to_language_tag.should == 'zh-hans-ch-u-co-pinyin'
|
73
|
+
else
|
74
|
+
Locale.new('en_US').to_language_tag.should == 'en-US'
|
75
|
+
Locale.new('zh_TW').to_language_tag.should == 'zh-TW'
|
76
|
+
Locale.new('zh_Hans_CH_PINYIN').to_language_tag.should == 'zh-Hans-CH-u-co-pinyin'
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe 'Win32 locale IDs' do
|
82
|
+
it 'converts an LCID to a locale' do
|
83
|
+
Locale.for_lcid(1033).should == Locale.new('en_US')
|
84
|
+
Locale.for_lcid(1036).should == Locale.new('fr_FR')
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'returns an LCID for a locale' do
|
88
|
+
Locale.new('en_US').lcid.should == 1033
|
89
|
+
Locale.new('es_US').lcid.should == 21514
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe 'display' do
|
94
|
+
context 'in a specific locale' do
|
95
|
+
it 'returns the country' do
|
96
|
+
Locale.new('de_DE').display_country('en').should == 'Germany'
|
97
|
+
Locale.new('en_US').display_country('fr').should == 'États-Unis'
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'returns the language' do
|
101
|
+
Locale.new('fr_FR').display_language('de').should == 'Französisch'
|
102
|
+
Locale.new('zh_CH').display_language('en').should == 'Chinese'
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'returns the name' do
|
106
|
+
Locale.new('en_US').display_name('de').should == 'Englisch (Vereinigte Staaten)'
|
107
|
+
Locale.new('zh_CH').display_name('fr').should == 'chinois (Suisse)'
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'returns the script' do
|
111
|
+
Locale.new('ja_Hira_JP').display_script('en').should == 'Hiragana'
|
112
|
+
Locale.new('ja_Hira_JP').display_script('ru').should == 'Хирагана'
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'returns the variant' do
|
116
|
+
Locale.new('zh_Hans_CH_PINYIN').display_variant('en').should == 'Pinyin Romanization'
|
117
|
+
|
118
|
+
if Gem::Version.new(Lib.cldr_version) > Gem::Version.new('1.8')
|
119
|
+
Locale.new('zh_Hans_CH_PINYIN').display_variant('es').should == 'Romanización pinyin'
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
context 'in the default locale' do
|
125
|
+
let(:locale) { Locale.new('de_DE') }
|
126
|
+
|
127
|
+
it 'returns the country' do
|
128
|
+
locale.display_country.should == locale.display_country(Locale.default)
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'returns the language' do
|
132
|
+
locale.display_language.should == locale.display_language(Locale.default)
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'returns the name' do
|
136
|
+
locale.display_name.should == locale.display_name(Locale.default)
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'returns the script' do
|
140
|
+
locale.display_script.should == locale.display_script(Locale.default)
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'returns the variant' do
|
144
|
+
locale.display_variant.should == locale.display_variant(Locale.default)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
describe 'formatting' do
|
150
|
+
let(:locale) { Locale.new('de-de.utf8@collation = phonebook') }
|
151
|
+
|
152
|
+
it('is formatted') { locale.name.should == 'de_DE.utf8@collation=phonebook' }
|
153
|
+
it('is formatted without keywords') { locale.base_name.should == 'de_DE.utf8' }
|
154
|
+
it('is formatted for ICU') { locale.canonical.should == 'de_DE@collation=phonebook' }
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'truncates a properly formatted locale, returning the "parent"' do
|
158
|
+
Locale.new('es-mx').parent.should == ''
|
159
|
+
Locale.new('es_MX').parent.should == 'es'
|
160
|
+
Locale.new('zh_Hans_CH_PINYIN').parent.should == 'zh_Hans_CH'
|
161
|
+
end
|
162
|
+
|
163
|
+
describe 'ISO codes' do
|
164
|
+
it 'returns the ISO 3166 alpha-3 country code' do
|
165
|
+
Locale.new('en_US').iso_country.should == 'USA'
|
166
|
+
Locale.new('zh_CN').iso_country.should == 'CHN'
|
167
|
+
end
|
168
|
+
|
169
|
+
it 'returns the ISO 639 three-letter language code' do
|
170
|
+
Locale.new('en_US').iso_language.should == 'eng'
|
171
|
+
Locale.new('zh_CN').iso_language.should == 'zho'
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
describe 'keywords' do
|
176
|
+
context 'when improperly formatted' do
|
177
|
+
let(:locale) { Locale.new('de_DE@euro') }
|
178
|
+
|
179
|
+
it 'raises an error' do
|
180
|
+
expect { locale.keywords }.to raise_error(ICU::Error)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
context 'when properly formatted' do
|
185
|
+
let(:locale) { Locale.new('de_DE@currency=EUR') }
|
186
|
+
|
187
|
+
it 'returns the list of keywords' do
|
188
|
+
locale.keywords.should == ['currency']
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
it 'can be read' do
|
193
|
+
Locale.new('en_US@calendar=chinese').keyword('calendar').should == 'chinese'
|
194
|
+
Locale.new('en_US@calendar=chinese').keyword(:calendar).should == 'chinese'
|
195
|
+
Locale.new('en_US@some=thing').keyword('missing').should == ''
|
196
|
+
end
|
197
|
+
|
198
|
+
it 'can be added' do
|
199
|
+
Locale.new('de_DE').with_keyword('currency', 'EUR').should == Locale.new('de_DE@currency=EUR')
|
200
|
+
Locale.new('de_DE').with_keyword(:currency, :EUR).should == Locale.new('de_DE@currency=EUR')
|
201
|
+
end
|
202
|
+
|
203
|
+
it 'can be added using hash' do
|
204
|
+
Locale.new('fr').with_keywords(:a => :b, :c => :d).should == Locale.new('fr@a=b;c=d')
|
205
|
+
end
|
206
|
+
|
207
|
+
it 'can be removed' do
|
208
|
+
Locale.new('en_US@some=thing').with_keyword(:some, nil).should == Locale.new('en_US')
|
209
|
+
Locale.new('en_US@some=thing').with_keyword(:some, '').should == Locale.new('en_US')
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
describe 'orientation' do
|
214
|
+
it 'returns the character orientation' do
|
215
|
+
Locale.new('ar').character_orientation.should == :rtl
|
216
|
+
Locale.new('en').character_orientation.should == :ltr
|
217
|
+
Locale.new('fa').character_orientation.should == :rtl
|
218
|
+
end
|
219
|
+
|
220
|
+
it 'returns the line orientation' do
|
221
|
+
Locale.new('ar').line_orientation.should == :ttb
|
222
|
+
Locale.new('en').line_orientation.should == :ttb
|
223
|
+
Locale.new('fa').line_orientation.should == :ttb
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
describe 'subtags' do
|
228
|
+
let(:locale) { Locale.new('zh-hans-ch-pinyin') }
|
229
|
+
|
230
|
+
it('returns the country code') { locale.country.should == 'CH' }
|
231
|
+
it('returns the language code') { locale.language.should == 'zh' }
|
232
|
+
it('returns the script code') { locale.script.should == 'Hans' }
|
233
|
+
it('returns the variant code') { locale.variant.should == 'PINYIN' }
|
234
|
+
|
235
|
+
describe 'likely subtags according to UTS #35' do
|
236
|
+
it 'adds likely subtags' do
|
237
|
+
Locale.new('en').with_likely_subtags.should == Locale.new('en_Latn_US')
|
238
|
+
Locale.new('sr').with_likely_subtags.should == Locale.new('sr_Cyrl_RS')
|
239
|
+
Locale.new('zh_TW').with_likely_subtags.should == Locale.new('zh_Hant_TW')
|
240
|
+
end
|
241
|
+
|
242
|
+
it 'removes likely subtags' do
|
243
|
+
Locale.new('en_US').with_minimized_subtags.should == Locale.new('en')
|
244
|
+
Locale.new('sr_RS').with_minimized_subtags.should == Locale.new('sr')
|
245
|
+
Locale.new('zh_Hant_TW').with_minimized_subtags.should == Locale.new('zh_TW')
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
data/spec/uchar_spec.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
module ICU
|
6
|
+
describe UCharPointer do
|
7
|
+
it 'allocates enough memory for 16-bit characters' do
|
8
|
+
UCharPointer.new(5).size.should == 10
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'builds a buffer from a string' do
|
12
|
+
ptr = UCharPointer.from_string('abc')
|
13
|
+
ptr.should be_a UCharPointer
|
14
|
+
ptr.size.should == 6
|
15
|
+
ptr.read_array_of_uint16(3).should == [0x61, 0x62, 0x63]
|
16
|
+
end
|
17
|
+
|
18
|
+
describe 'converting to string' do
|
19
|
+
let(:ptr) { UCharPointer.new(3).write_array_of_uint16 [0x78, 0x0, 0x79] }
|
20
|
+
|
21
|
+
it 'returns the the entire buffer by default' do
|
22
|
+
ptr.string.should == "x\0y"
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'returns strings of the specified length' do
|
26
|
+
ptr.string(0).should == ""
|
27
|
+
ptr.string(2).should == "x\0"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ffi-icu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -84,6 +84,8 @@ files:
|
|
84
84
|
- lib/ffi-icu/collation.rb
|
85
85
|
- lib/ffi-icu/core_ext/string.rb
|
86
86
|
- lib/ffi-icu/lib.rb
|
87
|
+
- lib/ffi-icu/lib/util.rb
|
88
|
+
- lib/ffi-icu/locale.rb
|
87
89
|
- lib/ffi-icu/normalization.rb
|
88
90
|
- lib/ffi-icu/transliteration.rb
|
89
91
|
- lib/ffi-icu/uchar.rb
|
@@ -91,10 +93,13 @@ files:
|
|
91
93
|
- spec/break_iterator_spec.rb
|
92
94
|
- spec/chardet_spec.rb
|
93
95
|
- spec/collation_spec.rb
|
96
|
+
- spec/lib_spec.rb
|
97
|
+
- spec/locale_spec.rb
|
94
98
|
- spec/normalization_spec.rb
|
95
99
|
- spec/spec.opts
|
96
100
|
- spec/spec_helper.rb
|
97
101
|
- spec/transliteration_spec.rb
|
102
|
+
- spec/uchar_spec.rb
|
98
103
|
- test.c
|
99
104
|
homepage: http://github.com/jarib/ffi-icu
|
100
105
|
licenses: []
|
@@ -125,8 +130,11 @@ test_files:
|
|
125
130
|
- spec/break_iterator_spec.rb
|
126
131
|
- spec/chardet_spec.rb
|
127
132
|
- spec/collation_spec.rb
|
133
|
+
- spec/lib_spec.rb
|
134
|
+
- spec/locale_spec.rb
|
128
135
|
- spec/normalization_spec.rb
|
129
136
|
- spec/spec.opts
|
130
137
|
- spec/spec_helper.rb
|
131
138
|
- spec/transliteration_spec.rb
|
139
|
+
- spec/uchar_spec.rb
|
132
140
|
has_rdoc:
|