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 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
- [ '/usr/local/{lib64,lib}', '/opt/local/{lib64,lib}', '/usr/{lib64,lib}' ]
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}, patches appreciated!"
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.put_array_of_uint16 0, bytes
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 = get_array_of_uint16(0, length)
32
+ wstring = read_array_of_uint16(length)
33
33
  wstring.pack("U*")
34
34
  end
35
35
 
@@ -1,3 +1,3 @@
1
1
  module ICU
2
- VERSION = "0.0.9"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -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("baah", "blah").should == -1
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
@@ -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
@@ -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.9
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: