ffi-icu 0.5.2 → 0.6.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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +10 -0
  3. data/LICENSE +1 -1
  4. data/README.md +21 -51
  5. data/Rakefile +4 -5
  6. data/ffi-icu.gemspec +34 -25
  7. data/lib/ffi-icu/break_iterator.rb +19 -18
  8. data/lib/ffi-icu/chardet.rb +12 -13
  9. data/lib/ffi-icu/collation.rb +62 -59
  10. data/lib/ffi-icu/duration_formatting.rb +293 -267
  11. data/lib/ffi-icu/lib/util.rb +10 -10
  12. data/lib/ffi-icu/lib.rb +273 -202
  13. data/lib/ffi-icu/locale.rb +14 -10
  14. data/lib/ffi-icu/normalization.rb +7 -7
  15. data/lib/ffi-icu/normalizer.rb +14 -8
  16. data/lib/ffi-icu/number_formatting.rb +41 -27
  17. data/lib/ffi-icu/time_formatting.rb +116 -93
  18. data/lib/ffi-icu/transliteration.rb +19 -19
  19. data/lib/ffi-icu/uchar.rb +14 -17
  20. data/lib/ffi-icu/version.rb +3 -1
  21. data/lib/ffi-icu.rb +16 -17
  22. metadata +35 -71
  23. data/.document +0 -5
  24. data/.gitignore +0 -23
  25. data/.rspec +0 -2
  26. data/.travis.yml +0 -28
  27. data/benchmark/detect.rb +0 -14
  28. data/benchmark/shared.rb +0 -17
  29. data/build_icu.sh +0 -53
  30. data/lib/ffi-icu/core_ext/string.rb +0 -9
  31. data/spec/break_iterator_spec.rb +0 -77
  32. data/spec/chardet_spec.rb +0 -42
  33. data/spec/collation_spec.rb +0 -84
  34. data/spec/duration_formatting_spec.rb +0 -143
  35. data/spec/lib/version_info_spec.rb +0 -20
  36. data/spec/lib_spec.rb +0 -63
  37. data/spec/locale_spec.rb +0 -280
  38. data/spec/normalization_spec.rb +0 -22
  39. data/spec/normalizer_spec.rb +0 -57
  40. data/spec/number_formatting_spec.rb +0 -79
  41. data/spec/spec_helper.rb +0 -13
  42. data/spec/time_spec.rb +0 -198
  43. data/spec/transliteration_spec.rb +0 -36
  44. data/spec/uchar_spec.rb +0 -34
  45. data/test.c +0 -56
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ICU
2
4
  class Locale
3
5
  class << self
@@ -43,16 +45,16 @@ module ICU
43
45
  attr_reader :id
44
46
 
45
47
  DISPLAY_CONTEXT = {
46
- length_full: 512, # UDISPCTX_LENGTH_FULL = (UDISPCTX_TYPE_DISPLAY_LENGTH<<8) + 0
47
- length_short: 513 # UDISPCTX_LENGTH_SHORT = (UDISPCTX_TYPE_DISPLAY_LENGTH<<8) + 1
48
- }
48
+ length_full: 512, # UDISPCTX_LENGTH_FULL = (UDISPCTX_TYPE_DISPLAY_LENGTH<<8) + 0
49
+ length_short: 513 # UDISPCTX_LENGTH_SHORT = (UDISPCTX_TYPE_DISPLAY_LENGTH<<8) + 1
50
+ }.freeze
49
51
 
50
52
  def initialize(id)
51
53
  @id = id.to_s
52
54
  end
53
55
 
54
56
  def ==(other)
55
- other.is_a?(self.class) && other.id == self.id
57
+ other.is_a?(self.class) && other.id == id
56
58
  end
57
59
 
58
60
  def base_name
@@ -104,9 +106,9 @@ module ICU
104
106
  def display_name_with_context(locale, contexts = [])
105
107
  contexts = DISPLAY_CONTEXT.select { |context| contexts.include?(context) }.values
106
108
 
107
- with_locale_display_name(@id, contexts) do |locale_display_names|
109
+ with_locale_display_name(locale, contexts) do |locale_display_names|
108
110
  Lib::Util.read_uchar_buffer(256) do |buffer, status|
109
- Lib.uldn_localeDisplayName(locale_display_names, locale, buffer, buffer.size, status)
111
+ Lib.uldn_localeDisplayName(locale_display_names, @id, buffer, buffer.size, status)
110
112
  end
111
113
  end
112
114
  end
@@ -183,13 +185,13 @@ module ICU
183
185
  end
184
186
  end
185
187
 
186
- def to_language_tag(strict = false)
188
+ def to_language_tag(strict = false) # rubocop:disable Style/OptionalBooleanParameter
187
189
  Lib::Util.read_string_buffer(64) do |buffer, status|
188
190
  Lib.uloc_toLanguageTag(@id, buffer, buffer.size, strict ? 1 : 0, status)
189
191
  end
190
192
  end
191
193
 
192
- alias_method :to_s, :id
194
+ alias to_s id
193
195
 
194
196
  def variant
195
197
  Lib::Util.read_string_buffer(64) do |buffer, status|
@@ -238,9 +240,11 @@ module ICU
238
240
 
239
241
  def with_locale_display_name(locale, contexts)
240
242
  pointer = FFI::MemoryPointer.new(:int, contexts.length).write_array_of_int(contexts)
241
- locale_display_names = ICU::Lib.check_error { |status| ICU::Lib.uldn_openForContext(locale, pointer, contexts.length, status) }
243
+ locale_display_names = ICU::Lib.check_error do |status|
244
+ ICU::Lib.uldn_openForContext(locale, pointer, contexts.length, status)
245
+ end
242
246
 
243
- yield locale_display_names
247
+ yield(locale_display_names)
244
248
  ensure
245
249
  Lib.uldn_close(locale_display_names) if locale_display_names
246
250
  end
@@ -1,8 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ICU
2
4
  module Normalization
3
-
4
5
  def self.normalize(input, mode = :default)
5
- input_length = input.jlength
6
+ input_length = input.size
6
7
  needed_length = out_length = options = 0
7
8
  in_ptr = UCharPointer.from_string(input)
8
9
  out_ptr = UCharPointer.new(out_length)
@@ -14,9 +15,9 @@ module ICU
14
15
  needed_length = Lib.unorm_normalize(in_ptr, input_length, mode, options, out_ptr, out_length, error)
15
16
  end
16
17
  rescue BufferOverflowError
17
- raise BufferOverflowError, "needed: #{needed_length}" if retried
18
+ raise(BufferOverflowError, "needed: #{needed_length}") if retried
18
19
 
19
- out_ptr = out_ptr.resized_to needed_length
20
+ out_ptr = out_ptr.resized_to(needed_length)
20
21
  out_length = needed_length + 1
21
22
 
22
23
  retried = true
@@ -25,6 +26,5 @@ module ICU
25
26
 
26
27
  out_ptr.string
27
28
  end
28
-
29
- end # Normalization
30
- end # ICU
29
+ end
30
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ICU
2
4
  class Normalizer
3
5
  # support for newer ICU normalization API
@@ -9,7 +11,7 @@ module ICU
9
11
  end
10
12
 
11
13
  def normalize(input)
12
- input_length = input.jlength
14
+ input_length = input.size
13
15
  in_ptr = UCharPointer.from_string(input)
14
16
  needed_length = capacity = 0
15
17
  out_ptr = UCharPointer.new(needed_length)
@@ -20,10 +22,10 @@ module ICU
20
22
  needed_length = Lib.unorm2_normalize(@instance, in_ptr, input_length, out_ptr, capacity, error)
21
23
  end
22
24
  rescue BufferOverflowError
23
- raise BufferOverflowError, "needed: #{needed_length}" if retried
25
+ raise(BufferOverflowError, "needed: #{needed_length}") if retried
24
26
 
25
27
  capacity = needed_length
26
- out_ptr = out_ptr.resized_to needed_length
28
+ out_ptr = out_ptr.resized_to(needed_length)
27
29
 
28
30
  retried = true
29
31
  retry
@@ -32,16 +34,20 @@ module ICU
32
34
  out_ptr.string
33
35
  end
34
36
 
35
- def is_normailzed?(input)
36
- input_length = input.jlength
37
+ def normailzed?(input)
38
+ input_length = input.size
37
39
  in_ptr = UCharPointer.from_string(input)
38
40
 
39
41
  Lib.check_error do |error|
40
- result = Lib.unorm2_isNormalized(@instance, in_ptr, input_length, error)
42
+ Lib.unorm2_isNormalized(@instance, in_ptr, input_length, error)
41
43
  end
42
44
 
43
45
  result
44
46
  end
45
47
 
46
- end # Normalizer
47
- end # ICU
48
+ def is_normalized?(input) # rubocop:disable Naming/PredicatePrefix
49
+ Warning.warn('is_normalized? is deprecated and will be removed after v0.7. Please use normalized? instead.')
50
+ normalized?(input)
51
+ end
52
+ end
53
+ end
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bigdecimal'
2
4
 
3
5
  module ICU
4
6
  module NumberFormatting
5
7
  @default_options = {}
6
-
8
+
7
9
  def self.create(locale, type = :decimal, options = {})
8
10
  case type
9
11
  when :currency
@@ -17,7 +19,7 @@ module ICU
17
19
  @default_options.clear
18
20
  end
19
21
 
20
- def self.set_default_options(options)
22
+ def self.set_default_options(options) # rubocop:disable Naming/AccessorMethodName
21
23
  @default_options.merge!(options)
22
24
  end
23
25
 
@@ -38,8 +40,7 @@ module ICU
38
40
  end
39
41
 
40
42
  class BaseFormatter
41
-
42
- def set_attributes(options)
43
+ def set_attributes(options) # rubocop:disable Naming/AccessorMethodName
43
44
  options.each { |key, value| Lib.unum_set_attribute(@f, key, value) }
44
45
  self
45
46
  end
@@ -47,13 +48,17 @@ module ICU
47
48
  private
48
49
 
49
50
  def make_formatter(type, locale)
50
- ptr = Lib.check_error { | error| Lib.unum_open(type, FFI::MemoryPointer.new(4), 0, locale, FFI::MemoryPointer.new(4), error) }
51
+ ptr = Lib.check_error do |error|
52
+ Lib.unum_open(type, FFI::MemoryPointer.new(4), 0, locale, FFI::MemoryPointer.new(4), error)
53
+ end
51
54
  FFI::AutoPointer.new(ptr, Lib.method(:unum_close))
52
55
  end
53
56
  end
54
57
 
55
58
  class NumberFormatter < BaseFormatter
56
59
  def initialize(locale, type = :decimal)
60
+ super()
61
+
57
62
  @f = make_formatter(type, locale)
58
63
  end
59
64
 
@@ -75,41 +80,48 @@ module ICU
75
80
  rescue RangeError
76
81
  # Fall back to stringifying in Ruby and passing that to ICU
77
82
  unless defined? Lib.unum_format_decimal
78
- raise RangeError,"Number #{number} is too big to fit in int64_t and your "\
79
- "ICU version is too old to have unum_format_decimal"
83
+ raise(RangeError, "Number #{number} is too big to fit in int64_t and your " \
84
+ 'ICU version is too old to have unum_format_decimal')
80
85
  end
81
86
  string_version = number.to_s
82
- needed_length = Lib.unum_format_decimal(@f, string_version, string_version.bytesize, out_ptr, needed_length, nil, error)
87
+ needed_length = Lib.unum_format_decimal(@f, string_version, string_version.size, out_ptr,
88
+ needed_length, nil, error)
83
89
  end
84
90
  when BigDecimal
85
91
  string_version = number.to_s('F')
86
- if Lib.respond_to? :unum_format_decimal
87
- needed_length = Lib.unum_format_decimal(@f, string_version, string_version.bytesize, out_ptr, needed_length, nil, error)
88
- else
89
- needed_length = Lib.unum_format_double(@f, number.to_f, out_ptr, needed_length, nil, error)
90
- end
92
+ needed_length = if Lib.respond_to?(:unum_format_decimal)
93
+ Lib.unum_format_decimal(@f, string_version, string_version.size, out_ptr,
94
+ needed_length, nil, error)
95
+ else
96
+ Lib.unum_format_double(@f, number.to_f, out_ptr, needed_length, nil, error)
97
+ end
91
98
  end
92
99
  end
93
- out_ptr.string needed_length
100
+ out_ptr.string(needed_length)
94
101
  rescue BufferOverflowError
95
- raise BufferOverflowError, "needed: #{needed_length}" if retried
96
- out_ptr = out_ptr.resized_to needed_length
102
+ raise(BufferOverflowError, "needed: #{needed_length}") if retried
103
+
104
+ out_ptr = out_ptr.resized_to(needed_length)
97
105
  retried = true
98
106
  retry
99
107
  end
100
108
  end
101
- end # NumberFormatter
109
+ end
102
110
 
103
111
  class CurrencyFormatter < BaseFormatter
104
112
  def initialize(locale, style = :default)
105
- if %w(iso plural).include?((style || '').to_s)
113
+ super()
114
+
115
+ if ['iso', 'plural'].include?((style || '').to_s)
106
116
  if Lib.version.to_a.first >= 53
107
- style = "currency_#{style}".to_sym
117
+ style = :"currency_#{style}"
108
118
  else
109
- fail "Your version of ICU (#{Lib.version.to_a.join('.')}) does not support #{style} currency formatting (supported only in version >= 53)"
119
+ raise("Your version of ICU (#{Lib.version.to_a.join('.')}) does not support " \
120
+ "#{style} currency formatting (supported only in version >= 53)")
110
121
  end
111
122
  elsif style && style.to_sym != :default
112
- fail "The ffi-icu ruby gem does not support :#{default} currency formatting (only :default, :iso, and :plural)"
123
+ raise('The ffi-icu ruby gem does not support: ' \
124
+ "#{default} currency formatting (only :default, :iso, and :plural)")
113
125
  else
114
126
  style = :currency
115
127
  end
@@ -124,16 +136,18 @@ module ICU
124
136
 
125
137
  begin
126
138
  Lib.check_error do |error|
127
- needed_length = Lib.unum_format_currency(@f, number, UCharPointer.from_string(currency, 4), out_ptr, needed_length, nil, error)
139
+ needed_length = Lib.unum_format_currency(@f, number, UCharPointer.from_string(currency, 4), out_ptr,
140
+ needed_length, nil, error)
128
141
  end
129
142
  out_ptr.string
130
143
  rescue BufferOverflowError
131
- raise BufferOverflowError, "needed: #{needed_length}" if retried
132
- out_ptr = out_ptr.resized_to needed_length
144
+ raise(BufferOverflowError, "needed: #{needed_length}") if retried
145
+
146
+ out_ptr = out_ptr.resized_to(needed_length)
133
147
  retried = true
134
148
  retry
135
149
  end
136
150
  end
137
- end # CurrencyFormatter
138
- end # Formatting
139
- end # ICU
151
+ end
152
+ end
153
+ end
@@ -1,53 +1,65 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'date'
2
4
 
3
5
  module ICU
4
6
  module TimeFormatting
5
7
  TZ_MAP = {
6
- :generic_location => 'VVVV',# The generic location format.
7
- # Where that is unavailable, falls back to the long localized GMT format ("OOOO";
8
- # Note: Fallback is only necessary with a GMT-style Time Zone ID, like Etc/GMT-830.),
9
- # This is especially useful when presenting possible timezone choices for user selection,
10
- # since the naming is more uniform than the "v" format.
11
- # such as "United States Time (New York)", "Italy Time"
12
- :generic_long => 'vvvv', # The long generic non-location format.
13
- # Where that is unavailable, falls back to generic location format ("VVVV")., such as "Eastern Time".
14
- :generic_short => 'v', # The short generic non-location format.
15
- # Where that is unavailable, falls back to the generic location format ("VVVV"),
16
- # then the short localized GMT format as the final fallback., such as "ET".
17
- :specific_long => 'zzzz', # The long specific non-location format.
18
- # Where that is unavailable, falls back to the long localized GMT format ("OOOO").
19
- :specific_short => 'z', # The short specific non-location format.
20
- # Where that is unavailable, falls back to the short localized GMT format ("O").
21
- :basic => 'Z', # The ISO8601 basic format with hours, minutes and optional seconds fields.
22
- # The format is equivalent to RFC 822 zone format (when optional seconds field is absent).
23
- # This is equivalent to the "xxxx" specifier.
24
- :localized_long => 'ZZZZ', # The long localized GMT format. This is equivalent to the "OOOO" specifier, such as GMT-8:00
25
- :extended => 'ZZZZZ', # The ISO8601 extended format with hours, minutes and optional seconds fields.
26
- # The ISO8601 UTC indicator "Z" is used when local time offset is 0.
27
- # This is equivalent to the "XXXXX" specifier, such as -08:00 -07:52:58
28
- :localized_short => 'O', # The short localized GMT format, such as GMT-8
29
- :localized_longO => 'OOOO', # The long localized GMT format, such as GMT-08:00
30
- :tz_id_short => 'V', # The short time zone ID. Where that is unavailable,
31
- # the special short time zone ID unk (Unknown Zone) is used.
32
- # Note: This specifier was originally used for a variant of the short specific non-location format,
33
- # but it was deprecated in the later version of this specification. In CLDR 23, the definition
34
- # of the specifier was changed to designate a short time zone ID, such as uslax
35
- :tz_id_long => 'VV', # The long time zone ID, such as America/Los_Angeles
36
- :city_location => 'VVV', # The exemplar city (location) for the time zone. Where that is unavailable,
37
- # the localized exemplar city name for the special zone Etc/Unknown is used as the fallback
38
- # (for example, "Unknown City"), such as Los Angeles
8
+ # The generic location format.
9
+ # Where that is unavailable, falls back to the long localized GMT format ("OOOO";
10
+ # Note: Fallback is only necessary with a GMT-style Time Zone ID, like Etc/GMT-830.),
11
+ # This is especially useful when presenting possible timezone choices for user selection,
12
+ # since the naming is more uniform than the "v" format.
13
+ # such as "United States Time (New York)", "Italy Time"
14
+ generic_location: 'VVVV',
15
+ # The long generic non-location format.
16
+ # Where that is unavailable, falls back to generic location format ("VVVV")., such as "Eastern Time".
17
+ generic_long: 'vvvv',
18
+ # The short generic non-location format.
19
+ # Where that is unavailable, falls back to the generic location format ("VVVV"),
20
+ # then the short localized GMT format as the final fallback., such as "ET".
21
+ generic_short: 'v',
22
+ # The long specific non-location format.
23
+ # Where that is unavailable, falls back to the long localized GMT format ("OOOO").
24
+ specific_long: 'zzzz',
25
+ # The short specific non-location format.
26
+ # Where that is unavailable, falls back to the short localized GMT format ("O").
27
+ specific_short: 'z',
28
+ # The ISO8601 basic format with hours, minutes and optional seconds fields.
29
+ # The format is equivalent to RFC 822 zone format (when optional seconds field is absent).
30
+ # This is equivalent to the "xxxx" specifier.
31
+ basic: 'Z',
32
+ # The long localized GMT format. This is equivalent to the "OOOO" specifier, such as GMT-8:00
33
+ localized_long: 'ZZZZ',
34
+ # The ISO8601 extended format with hours, minutes and optional seconds fields.
35
+ # The ISO8601 UTC indicator "Z" is used when local time offset is 0.
36
+ # This is equivalent to the "XXXXX" specifier, such as -08:00 -07:52:58
37
+ extended: 'ZZZZZ',
38
+ localized_short: 'O', # The short localized GMT format, such as GMT-8
39
+ localized_longO: 'OOOO', # The long localized GMT format, such as GMT-08:00
40
+ # The short time zone ID. Where that is unavailable,
41
+ # the special short time zone ID unk (Unknown Zone) is used.
42
+ # Note: This specifier was originally used for a variant of the short specific non-location format,
43
+ # but it was deprecated in the later version of this specification. In CLDR 23, the definition
44
+ # of the specifier was changed to designate a short time zone ID, such as uslax
45
+ tz_id_short: 'V',
46
+ tz_id_long: 'VV', # The long time zone ID, such as America/Los_Angeles
47
+ # The exemplar city (location) for the time zone. Where that is unavailable,
48
+ # the localized exemplar city name for the special zone Etc/Unknown is used as the fallback
49
+ # (for example, "Unknown City"), such as Los Angeles
39
50
  # see: http://unicode.org/reports/tr35/tr35-dates.html#Date_Format_Patterns
40
- }
51
+ city_location: 'VVV'
52
+ }.freeze
41
53
 
42
54
  HOUR_CYCLE_SYMS = {
43
55
  'h11' => 'K',
44
56
  'h12' => 'h',
45
57
  'h23' => 'H',
46
58
  'h24' => 'k',
47
- :locale => 'j',
48
- }
59
+ :locale => 'j'
60
+ }.freeze
49
61
  @default_options = {}
50
-
62
+
51
63
  def self.create(options = {})
52
64
  DateTimeFormatter.new(@default_options.merge(options))
53
65
  end
@@ -56,17 +68,16 @@ module ICU
56
68
  @default_options.clear
57
69
  end
58
70
 
59
- def self.set_default_options(options)
71
+ def self.set_default_options(options) # rubocop:disable Naming/AccessorMethodName
60
72
  @default_options.merge!(options)
61
73
  end
62
74
 
63
- def self.format(dt, options = {})
64
- create(@default_options.merge(options)).format(dt)
75
+ def self.format(datetime, options = {})
76
+ create(@default_options.merge(options)).format(datetime)
65
77
  end
66
78
 
67
79
  class BaseFormatter
68
-
69
- def set_attributes(options)
80
+ def set_attributes(options) # rubocop:disable Naming/AccessorMethodName
70
81
  options.each { |key, value| Lib.unum_set_attribute(@f, key, value) }
71
82
  self
72
83
  end
@@ -83,11 +94,11 @@ module ICU
83
94
  time_zone = UCharPointer.from_string(time_zone_str)
84
95
  tz_len = time_zone_str.size
85
96
  else
86
- Lib.check_error { | error|
87
- i_len = 150
97
+ Lib.check_error do |error|
98
+ i_len = 150
88
99
  time_zone = UCharPointer.new(i_len)
89
- tz_len = Lib.ucal_getDefaultTimeZone(time_zone, i_len, error)
90
- }
100
+ tz_len = Lib.ucal_getDefaultTimeZone(time_zone, i_len, error)
101
+ end
91
102
  end
92
103
 
93
104
  if skeleton
@@ -97,13 +108,17 @@ module ICU
97
108
  pattern_len, pattern_ptr = skeleton_format(skeleton, locale)
98
109
  end
99
110
 
100
- ptr = Lib.check_error { | error| Lib.udat_open(time_style, date_style, locale, time_zone, tz_len, pattern_ptr, pattern_len, error) }
111
+ ptr = Lib.check_error do |error|
112
+ Lib.udat_open(time_style, date_style, locale, time_zone, tz_len, pattern_ptr, pattern_len, error)
113
+ end
101
114
  FFI::AutoPointer.new(ptr, Lib.method(:udat_close))
102
115
  end
103
116
  end
104
117
 
105
118
  class DateTimeFormatter < BaseFormatter
106
- def initialize(options={})
119
+ def initialize(options = {})
120
+ super()
121
+
107
122
  time_style = options[:time] || :short
108
123
  date_style = options[:date] || :short
109
124
  @locale = options[:locale] || 'C'
@@ -113,31 +128,29 @@ module ICU
113
128
  @hour_cycle = options[:hour_cycle]
114
129
 
115
130
  if @hour_cycle && !HOUR_CYCLE_SYMS.keys.include?(@hour_cycle)
116
- raise ICU::Error.new("Unknown hour cycle #{@hour_cycle}")
131
+ raise(ICU::Error, "Unknown hour cycle #{@hour_cycle}")
117
132
  end
118
133
 
119
134
  @f = make_formatter(time_style, date_style, @locale, time_zone, skeleton)
120
135
  if tz_style
121
136
  f0 = date_format(true)
122
- f1 = update_tz_format(f0, tz_style)
123
- if f1 != f0
124
- set_date_format(true, f1)
125
- end
137
+ f1 = update_tz_format(f0, tz_style)
138
+ set_date_format(true, f1) if f1 != f0
126
139
  end
127
140
 
128
141
  replace_hour_symbol!
129
142
  end
130
143
 
131
144
  def parse(str)
132
- str_u = UCharPointer.from_string(str)
133
- str_l = str.size
134
- Lib.check_error do |error|
135
- ret = Lib.udat_parse(@f, str_u, str_l, nil, error)
136
- Time.at(ret / 1000.0)
137
- end
145
+ str_u = UCharPointer.from_string(str)
146
+ str_l = str.size
147
+ Lib.check_error do |error|
148
+ ret = Lib.udat_parse(@f, str_u, str_l, nil, error)
149
+ Time.at(ret / 1000.0)
150
+ end
138
151
  end
139
152
 
140
- def format(dt)
153
+ def format(datetime)
141
154
  needed_length = 0
142
155
  out_ptr = UCharPointer.new(needed_length)
143
156
 
@@ -145,18 +158,23 @@ module ICU
145
158
 
146
159
  begin
147
160
  Lib.check_error do |error|
148
- case dt
161
+ case datetime
149
162
  when Date
150
- needed_length = Lib.udat_format(@f, Time.mktime( dt.year, dt.month, dt.day, 0, 0, 0, 0 ).to_f * 1000.0, out_ptr, needed_length, nil, error)
163
+ needed_length = Lib.udat_format(
164
+ @f,
165
+ Time.mktime(datetime.year, datetime.month, datetime.day, 0, 0, 0, 0).to_f * 1000.0,
166
+ out_ptr, needed_length, nil, error
167
+ )
151
168
  when Time
152
- needed_length = Lib.udat_format(@f, dt.to_f * 1000.0, out_ptr, needed_length, nil, error)
169
+ needed_length = Lib.udat_format(@f, datetime.to_f * 1000.0, out_ptr, needed_length, nil, error)
153
170
  end
154
171
  end
155
172
 
156
173
  out_ptr.string
157
174
  rescue BufferOverflowError
158
- raise BufferOverflowError, "needed: #{needed_length}" if retried
159
- out_ptr = out_ptr.resized_to needed_length
175
+ raise(BufferOverflowError, "needed: #{needed_length}") if retried
176
+
177
+ out_ptr = out_ptr.resized_to(needed_length)
160
178
  retried = true
161
179
  retry
162
180
  end
@@ -164,19 +182,23 @@ module ICU
164
182
 
165
183
  # time-zone formating
166
184
  def update_tz_format(format, tz_style)
167
- return format if format !~ /(.*?)(\s*(?:[zZOVV]+\s*))(.*?)/
168
- pre, tz, suff = $1, $2, $3
185
+ return format if format !~ /(.*?)(\s*(?:[zZOV]+\s*))(.*?)/
186
+
187
+ pre = ::Regexp.last_match(1)
188
+ tz = ::Regexp.last_match(2)
189
+ suff = ::Regexp.last_match(3)
169
190
  if tz_style == :none
170
- tz = ((tz =~ /\s/) && !pre.empty? && !suff.empty?) ? ' ' : ''
191
+ tz = (tz =~ /\s/) && !pre.empty? && !suff.empty? ? ' ' : ''
171
192
  else
172
193
  repl = TZ_MAP[tz_style]
173
- raise 'no such tz_style' unless repl
174
- tz.gsub!(/^(\s*)(.*?)(\s*)$/, '\1'+repl+'\3')
194
+ raise('no such tz_style') unless repl
195
+
196
+ tz.gsub!(/^(\s*)(.*?)(\s*)$/, "\\1#{repl}\\3")
175
197
  end
176
198
  pre + tz + suff
177
199
  end
178
200
 
179
- def date_format(localized=true)
201
+ def date_format(localized = true) # rubocop:disable Style/OptionalBooleanParameter
180
202
  needed_length = 0
181
203
  out_ptr = UCharPointer.new(needed_length)
182
204
 
@@ -189,8 +211,9 @@ module ICU
189
211
 
190
212
  out_ptr.string
191
213
  rescue BufferOverflowError
192
- raise BufferOverflowError, "needed: #{needed_length}" if retried
193
- out_ptr = out_ptr.resized_to needed_length
214
+ raise(BufferOverflowError, "needed: #{needed_length}") if retried
215
+
216
+ out_ptr = out_ptr.resized_to(needed_length)
194
217
  retried = true
195
218
  retry
196
219
  end
@@ -205,26 +228,28 @@ module ICU
205
228
  end
206
229
 
207
230
  def skeleton_format(skeleton_pattern_str, locale)
208
- skeleton_pattern_ptr = UCharPointer.from_string(skeleton_pattern_str)
209
- skeleton_pattern_len = skeleton_pattern_str.size
231
+ skeleton_pattern_ptr = UCharPointer.from_string(skeleton_pattern_str)
232
+ skeleton_pattern_len = skeleton_pattern_str.size
210
233
 
211
- needed_length = 0
212
- pattern_ptr = UCharPointer.new(needed_length)
234
+ needed_length = 0
235
+ pattern_ptr = UCharPointer.new(needed_length)
213
236
 
214
- udatpg_ptr = Lib.check_error { |error| Lib.udatpg_open(locale, error) }
215
- generator = FFI::AutoPointer.new(udatpg_ptr, Lib.method(:udatpg_close))
237
+ udatpg_ptr = Lib.check_error { |error| Lib.udatpg_open(locale, error) }
238
+ generator = FFI::AutoPointer.new(udatpg_ptr, Lib.method(:udatpg_close))
216
239
 
217
- retried = false
240
+ retried = false
218
241
 
219
242
  begin
220
243
  Lib.check_error do |error|
221
- needed_length = Lib.udatpg_getBestPattern(generator, skeleton_pattern_ptr, skeleton_pattern_len, pattern_ptr, needed_length, error)
244
+ needed_length = Lib.udatpg_getBestPattern(generator, skeleton_pattern_ptr, skeleton_pattern_len,
245
+ pattern_ptr, needed_length, error)
222
246
  end
223
247
 
224
- return needed_length, pattern_ptr
248
+ [needed_length, pattern_ptr]
225
249
  rescue BufferOverflowError
226
- raise BufferOverflowError, "needed: #{needed_length}" if retried
227
- pattern_ptr = pattern_ptr.resized_to needed_length
250
+ raise(BufferOverflowError, "needed: #{needed_length}") if retried
251
+
252
+ pattern_ptr = pattern_ptr.resized_to(needed_length)
228
253
  retried = true
229
254
  retry
230
255
  end
@@ -255,9 +280,7 @@ module ICU
255
280
  # Either ensure the skeleton has, or does not have, am/pm, as appropriate
256
281
  if ['h11', 'h12'].include?(@hour_cycle)
257
282
  # Only actually append 'am/pm' if there is an hour in the format string
258
- if skeleton_str =~ /[hHkKjJ]/ && !skeleton_str.include?('a')
259
- skeleton_str << 'a'
260
- end
283
+ skeleton_str << 'a' if skeleton_str =~ /[hHkKjJ]/ && !skeleton_str.include?('a')
261
284
  else
262
285
  skeleton_str.gsub!('a', '')
263
286
  end
@@ -275,7 +298,7 @@ module ICU
275
298
  resolved_hour_cycle = @hour_cycle == :locale ? Locale.new(@locale).keyword('hours') : @hour_cycle
276
299
 
277
300
  if HOUR_CYCLE_SYMS.keys.include?(resolved_hour_cycle)
278
- new_pattern_str.gsub!(/[hHkK](?=(?:[^\']|\'[^\']*\')*$)/, HOUR_CYCLE_SYMS[resolved_hour_cycle])
301
+ new_pattern_str.gsub!(/[hHkK](?=(?:[^']|'[^']*')*$)/, HOUR_CYCLE_SYMS[resolved_hour_cycle])
279
302
  end
280
303
 
281
304
  # Finally, set the new pattern onto the date time formatter
@@ -325,10 +348,10 @@ module ICU
325
348
  pattern = UCharPointer.from_string(pattern_str)
326
349
  pattern_len = pattern_str.size
327
350
 
328
- Lib.check_error do |error|
329
- needed_length = Lib.udat_applyPattern(@f, localized, pattern, pattern_len)
351
+ Lib.check_error do |_error|
352
+ Lib.udat_applyPattern(@f, localized, pattern, pattern_len)
330
353
  end
331
354
  end
332
- end # DateTimeFormatter
333
- end # Formatting
334
- end # ICU
355
+ end
356
+ end
357
+ end