ffi-icu 0.0.9 → 0.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.
- 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:
|