icu 0.9.1 → 0.10.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 (54) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -0
  3. data/.travis.yml +11 -0
  4. data/Gemfile +3 -0
  5. data/LICENSE +20 -0
  6. data/README.md +69 -0
  7. data/Rakefile +38 -0
  8. data/benchmark/normalization.rb +106 -0
  9. data/benchmark/normalization_phrases.txt +1031 -0
  10. data/benchmark/normalization_result.txt +45 -0
  11. data/benchmark/normalization_wikip.txt +2838 -0
  12. data/ext/icu/extconf.rb +242 -0
  13. data/ext/icu/icu.c +18 -0
  14. data/ext/icu/icu.h +78 -0
  15. data/ext/icu/icu_charset_detector.c +192 -0
  16. data/ext/icu/icu_collator.c +138 -0
  17. data/ext/icu/icu_locale.c +852 -0
  18. data/ext/icu/icu_normalizer.c +122 -0
  19. data/ext/icu/icu_number_format.c +0 -0
  20. data/ext/icu/icu_spoof_checker.c +194 -0
  21. data/ext/icu/icu_transliterator.c +159 -0
  22. data/ext/icu/internal_encoding.c +38 -0
  23. data/ext/icu/internal_ustring.c +304 -0
  24. data/ext/icu/internal_utils.c +50 -0
  25. data/ext/icu/rb_errors.c +14 -0
  26. data/icu.gemspec +22 -0
  27. data/lib/icu.rb +6 -18
  28. data/lib/icu/charset_detector.rb +5 -0
  29. data/lib/icu/collator.rb +24 -0
  30. data/lib/icu/locale.rb +19 -0
  31. data/lib/icu/transliterator.rb +8 -0
  32. data/lib/icu/version.rb +3 -0
  33. data/spec/charset_detector_spec.rb +47 -0
  34. data/spec/collator_spec.rb +73 -0
  35. data/spec/locale_spec.rb +312 -0
  36. data/spec/normalizer_spec.rb +35 -0
  37. data/spec/spec_helper.rb +8 -0
  38. data/spec/spoof_checker_spec.rb +56 -0
  39. data/spec/transliterator_spec.rb +41 -0
  40. metadata +132 -55
  41. data/COPYING +0 -674
  42. data/COPYING.LESSER +0 -165
  43. data/README +0 -81
  44. data/ext/extconf.rb +0 -31
  45. data/ext/icu.c +0 -128
  46. data/ext/icu.h +0 -34
  47. data/ext/icu_locale.c +0 -330
  48. data/ext/icu_locale_country.c +0 -99
  49. data/ext/icu_locale_language.c +0 -99
  50. data/ext/icu_numeric.c +0 -161
  51. data/ext/icu_time.c +0 -391
  52. data/test/test_locale.rb +0 -73
  53. data/test/test_numeric.rb +0 -78
  54. data/test/test_time.rb +0 -75
@@ -1,99 +0,0 @@
1
- // Copyright (c) 2007 Joshua Llorach
2
- //
3
- // This file is part of ICU Ruby extension.
4
- //
5
- // ICU is free software: you can redistribute it and/or modify
6
- // it under the terms of the GNU Lesser General Public License as published by
7
- // the Free Software Foundation, either version 3 of the License, or
8
- // (at your option) any later version.
9
- //
10
- // ICU is distributed in the hope that it will be useful,
11
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- // GNU Lesser General Public License for more details.
14
- //
15
- // You should have received a copy of the GNU Lesser General Public License
16
- // along with ICU. If not, see <http://www.gnu.org/licenses/>.
17
-
18
- #include "icu.h"
19
-
20
- VALUE cCountry;
21
-
22
- /******************* ICU::Locale::Country */
23
-
24
- /**
25
- * call-seq:
26
- * ICU::Locale.get => locale
27
- */
28
- VALUE rb_Country_class_get(VALUE self, VALUE code)
29
- {
30
- VALUE countries, country;
31
-
32
- code = StringValue(code);
33
- countries = rb_cv_get(self, "@@countries");
34
- country = rb_hash_aref(countries, code);
35
- if (country == Qnil) {
36
- VALUE args[1];
37
-
38
- args[0] = code;
39
- country = rb_class_new_instance(1, args, self);
40
- rb_hash_aset(countries, code, country);
41
- return country;
42
- } else {
43
- return country;
44
- }
45
- }
46
-
47
- VALUE rb_Country_initialize(VALUE self, VALUE code)
48
- {
49
- code = StringValue(code);
50
- CheckCountryCode(RSTRING(code)->ptr);
51
- rb_iv_set(self, "@code", code);
52
-
53
- return self;
54
- }
55
-
56
- VALUE rb_Country_name(int argc, VALUE *argv, VALUE self)
57
- {
58
- char fakeLocale[4] = "_";
59
- VALUE code = rb_iv_get(self, "@code");
60
-
61
- VALUE rb_locale;
62
- char * locale = NULL;
63
-
64
- UChar * country = ALLOC_N(UChar, 32);
65
- int32_t countryLen = 32;
66
- UErrorCode status = U_ZERO_ERROR;
67
-
68
- strcat(fakeLocale, RSTRING(code)->ptr);
69
-
70
- rb_scan_args(argc, argv, "01", &rb_locale);
71
- if (rb_locale != Qnil) {
72
- locale = StringValuePtr(rb_locale);
73
- }
74
-
75
- countryLen = uloc_getDisplayCountry(fakeLocale, locale, country, countryLen, &status);
76
- if (status == U_BUFFER_OVERFLOW_ERROR) {
77
- status = U_ZERO_ERROR;
78
- REALLOC_N(country, UChar, countryLen);
79
- uloc_getDisplayCountry(fakeLocale, locale, country, countryLen, &status);
80
- }
81
- RAISE_ON_ERROR(status);
82
-
83
- return u_strToRString(country, countryLen);
84
- }
85
-
86
- void Init_ICU_Locale_Country()
87
- {
88
- extern VALUE cLocale;
89
-
90
- cCountry = rb_define_class_under(cLocale, "Country", rb_cObject);
91
- rb_funcall(cCountry, rb_intern("private_class_method"), 1, ID2SYM(rb_intern("new")));
92
- rb_cv_set(cCountry, "@@countries", rb_hash_new());
93
- rb_define_singleton_method(cCountry, "get", rb_Country_class_get, 1);
94
- rb_define_private_method(cCountry, "initialize", rb_Country_initialize, 1);
95
- rb_define_attr(cCountry, "code", 1, 0);
96
- rb_define_alias(cCountry, "to_str", "code");
97
- rb_define_alias(cCountry, "to_s", "code");
98
- rb_define_method(cCountry, "name", rb_Country_name, -1);
99
- }
@@ -1,99 +0,0 @@
1
- // Copyright (c) 2007 Joshua Llorach
2
- //
3
- // This file is part of ICU Ruby extension.
4
- //
5
- // ICU is free software: you can redistribute it and/or modify
6
- // it under the terms of the GNU Lesser General Public License as published by
7
- // the Free Software Foundation, either version 3 of the License, or
8
- // (at your option) any later version.
9
- //
10
- // ICU is distributed in the hope that it will be useful,
11
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- // GNU Lesser General Public License for more details.
14
- //
15
- // You should have received a copy of the GNU Lesser General Public License
16
- // along with ICU. If not, see <http://www.gnu.org/licenses/>.
17
-
18
- #include "icu.h"
19
-
20
- VALUE cLanguage;
21
-
22
- /******************* ICU::Locale::Language */
23
-
24
- /**
25
- * call-seq:
26
- * ICU::Locale.get => locale
27
- */
28
- VALUE rb_Language_class_get(VALUE self, VALUE code)
29
- {
30
- VALUE languages, language;
31
-
32
- code = StringValue(code);
33
- languages = rb_cv_get(self, "@@languages");
34
- language = rb_hash_aref(languages, code);
35
- if (language == Qnil) {
36
- VALUE args[1];
37
-
38
- args[0] = code;
39
- language = rb_class_new_instance(1, args, self);
40
- rb_hash_aset(languages, code, language);
41
- return language;
42
- } else {
43
- return language;
44
- }
45
- }
46
-
47
- VALUE rb_Language_initialize(VALUE self, VALUE code)
48
- {
49
- code = StringValue(code);
50
- CheckLanguageCode(RSTRING(code)->ptr);
51
- rb_iv_set(self, "@code", code);
52
-
53
- return self;
54
- }
55
-
56
- VALUE rb_Language_name(int argc, VALUE *argv, VALUE self)
57
- {
58
- char *fakeLocale;
59
- VALUE code = rb_iv_get(self, "@code");
60
-
61
- VALUE rb_locale;
62
- char *locale = NULL;
63
-
64
- UChar *language = ALLOC_N(UChar, 32);
65
- int32_t languageLen = 32;
66
- UErrorCode status = U_ZERO_ERROR;
67
-
68
- fakeLocale = RSTRING(code)->ptr;
69
-
70
- rb_scan_args(argc, argv, "01", &rb_locale);
71
- if (rb_locale != Qnil) {
72
- locale = StringValuePtr(rb_locale);
73
- }
74
-
75
- languageLen = uloc_getDisplayLanguage(fakeLocale, locale, language, languageLen, &status);
76
- if (status == U_BUFFER_OVERFLOW_ERROR) {
77
- status = U_ZERO_ERROR;
78
- REALLOC_N(language, UChar, languageLen);
79
- uloc_getDisplayLanguage(fakeLocale, locale, language, languageLen, &status);
80
- }
81
- RAISE_ON_ERROR(status);
82
-
83
- return u_strToRString(language, languageLen);
84
- }
85
-
86
- void Init_ICU_Locale_Language()
87
- {
88
- extern VALUE cLocale;
89
-
90
- cLanguage = rb_define_class_under(cLocale, "Language", rb_cObject);
91
- rb_funcall(cLanguage, rb_intern("private_class_method"), 1, ID2SYM(rb_intern("new")));
92
- rb_cv_set(cLanguage, "@@languages", rb_hash_new());
93
- rb_define_singleton_method(cLanguage, "get", rb_Language_class_get, 1);
94
- rb_define_private_method(cLanguage, "initialize", rb_Language_initialize, 1);
95
- rb_define_attr(cLanguage, "code", 1, 0);
96
- rb_define_alias(cLanguage, "to_str", "code");
97
- rb_define_alias(cLanguage, "to_s", "code");
98
- rb_define_method(cLanguage, "name", rb_Language_name, -1);
99
- }
@@ -1,161 +0,0 @@
1
- // Copyright (c) 2007 Joshua Llorach
2
- //
3
- // This file is part of ICU Ruby extension.
4
- //
5
- // ICU is free software: you can redistribute it and/or modify
6
- // it under the terms of the GNU Lesser General Public License as published by
7
- // the Free Software Foundation, either version 3 of the License, or
8
- // (at your option) any later version.
9
- //
10
- // ICU is distributed in the hope that it will be useful,
11
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- // GNU Lesser General Public License for more details.
14
- //
15
- // You should have received a copy of the GNU Lesser General Public License
16
- // along with ICU. If not, see <http://www.gnu.org/licenses/>.
17
-
18
- #include "icu.h"
19
-
20
- #include "unicode/unum.h"
21
-
22
- /******************* Numeric */
23
-
24
- /**
25
- * call-seq:
26
- * 23874.localize(:decimal, 'es_ES') => 23.874
27
- */
28
- VALUE rb_numeric_localize(int argc, VALUE *argv, VALUE self)
29
- {
30
- VALUE style, options;
31
- UNumberFormatStyle formatStyle;
32
- char *locale = NULL;
33
-
34
- UNumberFormat *format;
35
- UErrorCode status;
36
-
37
- UChar result[256];
38
- /* arguments */
39
- rb_scan_args(argc, argv, "02", &style, &options);
40
- if (style == Qnil) {
41
- formatStyle = UNUM_DECIMAL;
42
- } else {
43
- ID style_ID;
44
-
45
- Check_Type(style, T_SYMBOL);
46
- style_ID = SYM2ID(style);
47
- if (style_ID == rb_intern("decimal")) {
48
- formatStyle = UNUM_DECIMAL;
49
- } else if (style_ID == rb_intern("currency")) {
50
- formatStyle = UNUM_CURRENCY;
51
- } else if (style_ID == rb_intern("percent")) {
52
- formatStyle = UNUM_PERCENT;
53
- } else if (style_ID == rb_intern("scientific")) {
54
- formatStyle = UNUM_SCIENTIFIC;
55
- } else if (style_ID == rb_intern("spellout")) {
56
- formatStyle = UNUM_SPELLOUT;
57
- } else {
58
- rb_raise(rb_eArgError, "unsupported format style %s", rb_id2name(style_ID));
59
- }
60
- }
61
- if (options != Qnil) {
62
- VALUE rb_locale;
63
-
64
- Check_Type(options, T_HASH);
65
- rb_locale = rb_hash_aref(options, ID2SYM(rb_intern("locale")));
66
- if (rb_locale != Qnil) {
67
- locale = StringValuePtr(rb_locale);
68
- }
69
- }
70
- /* formatter */
71
- status = U_ZERO_ERROR;
72
- format = unum_open(formatStyle, NULL, 0, locale, NULL, &status);
73
- RAISE_ON_ERROR(status);
74
- /* set format attributes */
75
- if (options != Qnil) {
76
- VALUE currency, precision, round_mode, round_increment;
77
-
78
- switch (formatStyle) {
79
- case UNUM_CURRENCY:
80
- currency = rb_hash_aref(options, ID2SYM(rb_intern("currency")));
81
- if (currency != Qnil) {
82
- UChar *uStr;
83
- int32_t uStrLen;
84
-
85
- uStr = u_strFromRString(currency, &uStrLen);
86
- status = U_ZERO_ERROR;
87
- unum_setTextAttribute(format, UNUM_CURRENCY_CODE, uStr, uStrLen, &status);
88
- RAISE_ON_ERROR(status);
89
- }
90
- case UNUM_DECIMAL:
91
- /* precision */
92
- precision = rb_hash_aref(options, ID2SYM(rb_intern("precision")));
93
- if (precision != Qnil) {
94
- Check_Type(precision, T_FIXNUM);
95
- status = U_ZERO_ERROR;
96
- unum_setAttribute(format, UNUM_FRACTION_DIGITS, NUM2INT(precision));
97
- RAISE_ON_ERROR(status);
98
- }
99
-
100
- round_mode = rb_hash_aref(options, ID2SYM(rb_intern("round_mode")));
101
- if (round_mode != Qnil) {
102
- ID round_mode_ID;
103
- UNumberFormatRoundingMode rounding_mode;
104
-
105
- Check_Type(round_mode, T_SYMBOL);
106
- round_mode_ID = SYM2ID(round_mode);
107
- if (round_mode_ID == rb_intern("ceil")) {
108
- rounding_mode = UNUM_ROUND_CEILING;
109
- } else if (round_mode_ID == rb_intern("floor")) {
110
- rounding_mode = UNUM_ROUND_FLOOR;
111
- } else if (round_mode_ID == rb_intern("down")) {
112
- rounding_mode = UNUM_ROUND_DOWN;
113
- } else if (round_mode_ID == rb_intern("up")) {
114
- rounding_mode = UNUM_ROUND_UP;
115
- } else if (round_mode_ID == rb_intern("halfeven")) {
116
- rounding_mode = UNUM_FOUND_HALFEVEN;
117
- } else if (round_mode_ID == rb_intern("halfdown")) {
118
- rounding_mode = UNUM_ROUND_HALFDOWN;
119
- } else if (round_mode_ID == rb_intern("halfup")) {
120
- rounding_mode = UNUM_ROUND_HALFUP;
121
- } else {
122
- rb_raise(rb_eArgError, "unsupported rounding mode '%s'", rb_id2name(round_mode_ID));
123
- }
124
- status = U_ZERO_ERROR;
125
- unum_setAttribute(format, UNUM_ROUNDING_MODE, rounding_mode);
126
- RAISE_ON_ERROR(status);
127
- }
128
- round_increment = rb_hash_aref(options, ID2SYM(rb_intern("round_increment")));
129
- if (round_increment != Qnil) {
130
- Check_Type(round_increment, T_FLOAT);
131
- status = U_ZERO_ERROR;
132
- unum_setDoubleAttribute(format, UNUM_ROUNDING_INCREMENT, NUM2DBL(round_increment));
133
- RAISE_ON_ERROR(status);
134
- }
135
- }
136
- }
137
- /* format */
138
- status = U_ZERO_ERROR;
139
- switch (TYPE(self)) {
140
- case T_FIXNUM:
141
- unum_format(format, NUM2INT(self), result, 256, NULL, &status);
142
- break;
143
- case T_FLOAT:
144
- unum_formatDouble(format, NUM2DBL(self), result, 256, NULL, &status);
145
- break;
146
- case T_BIGNUM:
147
- unum_formatInt64(format, rb_big2ll(self), result, 256, NULL, &status);
148
- break;
149
-
150
- }
151
- RAISE_ON_ERROR(status);
152
- /* free resources */
153
- unum_close(format);
154
-
155
- return u_strToRString(result, -1);
156
- }
157
-
158
- void Init_ICU_Numeric(void)
159
- {
160
- rb_define_method(rb_cNumeric, "localize", rb_numeric_localize, -1);
161
- }
@@ -1,391 +0,0 @@
1
- // Copyright (c) 2007 Joshua Llorach
2
- //
3
- // This file is part of ICU Ruby extension.
4
- //
5
- // ICU is free software: you can redistribute it and/or modify
6
- // it under the terms of the GNU Lesser General Public License as published by
7
- // the Free Software Foundation, either version 3 of the License, or
8
- // (at your option) any later version.
9
- //
10
- // ICU is distributed in the hope that it will be useful,
11
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- // GNU Lesser General Public License for more details.
14
- //
15
- // You should have received a copy of the GNU Lesser General Public License
16
- // along with ICU. If not, see <http://www.gnu.org/licenses/>.
17
-
18
- #include "icu.h"
19
-
20
- #include "unicode/ucal.h"
21
- #include "unicode/udat.h"
22
-
23
- /******************* Time */
24
-
25
- /**
26
- * call-seq:
27
- * 23874.localize(:date => :short) => 23.874
28
- */
29
- VALUE rb_Time_localize(int argc, VALUE *argv, VALUE self)
30
- {
31
- VALUE options;
32
- UDateFormatStyle dateStyle = UDAT_DEFAULT, timeStyle = UDAT_DEFAULT;
33
- char *locale = NULL;
34
- const UChar *timeZone = 0;
35
- int32_t timeZoneLen = -1;
36
-
37
- UDateFormat *format;
38
- UErrorCode status;
39
- UChar result[256];
40
- /* arguments */
41
- rb_scan_args(argc, argv, "01", &options);
42
- if (options != Qnil) {
43
- VALUE rb_locale, rb_timeZone;
44
-
45
- Check_Type(options, T_HASH);
46
- /* date and time style */
47
- dateStyle = getStyle(options, "date");
48
- timeStyle = getStyle(options, "time");
49
- /* locale */
50
- rb_locale = rb_hash_aref(options, ID2SYM(rb_intern("locale")));
51
- if (rb_locale != Qnil) {
52
- locale = StringValuePtr(rb_locale);
53
- }
54
- /* time zone */
55
- rb_timeZone = rb_hash_aref(options, ID2SYM(rb_intern("zone")));
56
- if (rb_timeZone != Qnil) {
57
- Check_Type(rb_timeZone, T_STRING);
58
- timeZone = u_strFromRString(rb_timeZone, &timeZoneLen);
59
- }
60
- }
61
-
62
- /* formatter */
63
- status = U_ZERO_ERROR;
64
- format = udat_open(timeStyle, dateStyle, locale, timeZone, timeZoneLen, NULL, -1, &status);
65
- RAISE_ON_ERROR(status);
66
- /* format */
67
- status = U_ZERO_ERROR;
68
- {
69
- extern struct timeval rb_time_timeval(VALUE time);
70
- struct timeval tv;
71
- UDate dateToFormat;
72
- UChar result[256];
73
-
74
- tv = rb_time_timeval(self);
75
- dateToFormat = ((double)tv.tv_sec + (double)tv.tv_usec / 1e6) * 1e3;
76
- udat_format(format, dateToFormat, result, 256, NULL, &status);
77
- RAISE_ON_ERROR(status);
78
- /* free resources */
79
- unum_close(format);
80
-
81
- return u_strToRString(result, -1);
82
- }
83
- }
84
-
85
- UDateFormatStyle getStyle(VALUE options, const char * key)
86
- {
87
- UDateFormatStyle formatStyle = UDAT_DEFAULT;
88
- VALUE style;
89
-
90
- style = rb_hash_aref(options, ID2SYM(rb_intern(key)));
91
- if (style != Qnil) {
92
- if (style == Qfalse) {
93
- formatStyle = UDAT_NONE;
94
- } else {
95
- ID style_ID;
96
-
97
- Check_Type(style, T_SYMBOL);
98
- style_ID = SYM2ID(style);
99
- if (style_ID == rb_intern("full")) {
100
- formatStyle = UDAT_FULL;
101
- } else if (style_ID == rb_intern("long")) {
102
- formatStyle = UDAT_LONG;
103
- } else if (style_ID == rb_intern("medium")) {
104
- formatStyle = UDAT_MEDIUM;
105
- } else if (style_ID == rb_intern("short")) {
106
- formatStyle = UDAT_SHORT;
107
- } else {
108
- rb_raise(rb_eArgError, "unsupported format style %s", rb_id2name(style_ID));
109
- }
110
- }
111
- }
112
-
113
- return formatStyle;
114
- }
115
-
116
- VALUE enumToOptions(UEnumeration *enumeration, VALUE options, UCalendar *calendar, UCalendarDisplayNameType type, char *locale)
117
- {
118
- const UChar *zoneID;
119
- int32_t zoneIDLen;
120
- UErrorCode status = U_ZERO_ERROR;
121
-
122
- while (zoneID = uenum_unext(enumeration, &zoneIDLen, &status)) {
123
- RAISE_ON_ERROR(status);
124
- if (type == -1) {
125
- rb_ary_push(options, u_strToRString(zoneID, zoneIDLen));
126
- } else {
127
- VALUE option = rb_ary_new2(2);
128
- UChar *zoneName = ALLOC_N(UChar, 64);
129
- int32_t zoneNameLen = 64;
130
-
131
- ucal_setTimeZone(calendar, zoneID, zoneIDLen, &status);
132
- RAISE_ON_ERROR(status);
133
- zoneNameLen = ucal_getTimeZoneDisplayName(calendar, UCAL_STANDARD, locale, zoneName, zoneNameLen, &status);
134
- if (status == U_BUFFER_OVERFLOW_ERROR) {
135
- status = U_ZERO_ERROR;
136
- REALLOC_N(zoneName, UChar, zoneNameLen);
137
- ucal_getTimeZoneDisplayName(calendar, UCAL_STANDARD, locale, zoneName, zoneNameLen, &status);
138
- }
139
- RAISE_ON_ERROR(status);
140
- rb_ary_push(option, u_strToRString(zoneName, zoneNameLen));
141
- rb_ary_push(option, u_strToRString(zoneID, zoneIDLen));
142
- rb_ary_push(options, option);
143
- }
144
- }
145
-
146
- return options;
147
- }
148
-
149
- /**
150
- * call-seq:
151
- * Time.zones(:countries => ['US'], :locale => 'es_ES', :type => :short) => 23.874
152
- * Time.zones(:countries => :all, :group => true) => 23.874
153
- */
154
- VALUE rb_Time_singleton_zones(int argc, VALUE *argv, VALUE self)
155
- {
156
- VALUE options, countries = Qfalse, group = Qfalse;
157
- char *locale = NULL;
158
- UCalendarDisplayNameType type = -1;
159
-
160
- UCalendar *calendar;
161
- UErrorCode status = U_ZERO_ERROR;
162
- UEnumeration *enumeration;
163
- VALUE select = rb_ary_new();
164
- UCollator *collator;
165
-
166
- //arguments
167
- rb_scan_args(argc, argv, "01", &options);
168
- if (options != Qnil) {
169
- VALUE rb_locale, rb_type;
170
-
171
- Check_Type(options, T_HASH);
172
- //locale
173
- rb_locale = rb_hash_aref(options, ID2SYM(rb_intern("locale")));
174
- if (rb_locale != Qnil) {
175
- locale = StringValuePtr(rb_locale);
176
- }
177
- //countries
178
- countries = rb_hash_aref(options, ID2SYM(rb_intern("countries")));
179
- if (countries == Qnil) {
180
- countries = Qfalse;
181
- } else {
182
-
183
- }
184
- //group
185
- group = rb_hash_aref(options, ID2SYM(rb_intern("group")));
186
- group = group && group != Qnil ? Qtrue : Qfalse;
187
- //type
188
- rb_type = rb_hash_aref(options, ID2SYM(rb_intern("type")));
189
- if (rb_type != Qnil) {
190
- ID rb_type_ID;
191
-
192
- Check_Type(rb_type, T_SYMBOL);
193
- rb_type_ID = SYM2ID(rb_type);
194
- if (rb_type_ID == rb_intern("standard")) {
195
- type = UCAL_STANDARD;
196
- } else if (rb_type_ID == rb_intern("short_standard")) {
197
- type = UCAL_SHORT_STANDARD;
198
- } else if (rb_type_ID == rb_intern("dst")) {
199
- type = UCAL_DST;
200
- } else if (rb_type_ID == rb_intern("short_dst")) {
201
- type = UCAL_SHORT_DST;
202
- } else {
203
- rb_raise(rb_eArgError, "unsupported time zone type %s", rb_id2name(rb_type_ID));
204
- }
205
- }
206
- }
207
- //calendar
208
- calendar = ucal_open(NULL, -1, locale, UCAL_GREGORIAN, &status);
209
- RAISE_ON_ERROR(status);
210
-
211
- collator = ucol_open(locale, &status);
212
- RAISE_ON_ERROR(status);
213
-
214
- if (countries) {
215
- const char* const* isoCountries = uloc_getISOCountries();
216
-
217
- while (*isoCountries != NULL) {
218
- if (TYPE(countries) == T_SYMBOL || (TYPE(countries) == T_ARRAY && rb_ary_includes(countries, rb_str_new2(*isoCountries)))) {
219
- if (group) {
220
- char fakeLocale[4] = "_";
221
- UChar *country = ALLOC_N(UChar, 32);
222
- int32_t countryLen = 32;
223
- VALUE optgroup = rb_ary_new2(2);
224
-
225
- strcat(fakeLocale, *isoCountries);
226
- countryLen = uloc_getDisplayCountry(fakeLocale, locale, country, countryLen, &status);
227
- if (status == U_BUFFER_OVERFLOW_ERROR) {
228
- status = U_ZERO_ERROR;
229
- REALLOC_N(country, UChar, countryLen);
230
- uloc_getDisplayCountry(fakeLocale, locale, country, countryLen, &status);
231
- }
232
- rb_ary_push(optgroup, u_strToRString(country, countryLen));
233
- enumeration = ucal_openCountryTimeZones(*isoCountries, &status);
234
- RAISE_ON_ERROR(status);
235
- rb_ary_push(optgroup, enumToOptions(enumeration, rb_ary_new(), calendar, type, locale));
236
- uenum_close(enumeration);
237
- if (RARRAY(RARRAY(optgroup)->ptr[1])->len) {
238
- ruby_qsort(RARRAY(RARRAY(optgroup)->ptr[1])->ptr, RARRAY(RARRAY(optgroup)->ptr[1])->len, sizeof(VALUE), collateByDisplayName, collator);
239
- rb_ary_push(select, optgroup);
240
- }
241
- } else {
242
- enumeration = ucal_openCountryTimeZones(*isoCountries, &status);
243
- RAISE_ON_ERROR(status);
244
- enumToOptions(enumeration, select, calendar, type, locale);
245
- uenum_close(enumeration);
246
- }
247
- }
248
- *isoCountries++;
249
- }
250
- } else {
251
- enumeration = ucal_openTimeZones(&status);
252
- RAISE_ON_ERROR(status);
253
- enumToOptions(enumeration, select, calendar, type, locale);
254
- uenum_close(enumeration);
255
- }
256
- //sort
257
- ruby_qsort(RARRAY(select)->ptr, RARRAY(select)->len, sizeof(VALUE), collateByDisplayName, collator);
258
- //free
259
- ucal_close(calendar);
260
- ucol_close(collator);
261
-
262
- return select;
263
- }
264
-
265
- /**
266
- * call-seq:
267
- * Time.default_zone = 'GMT'
268
- */
269
- VALUE rb_Time_singleton_set_default_zone(VALUE self, VALUE zone)
270
- {
271
- UErrorCode status = U_ZERO_ERROR;
272
-
273
- ucal_setDefaultTimeZone((const UChar *)u_strFromRString(zone, NULL), &status);
274
- RAISE_ON_ERROR(status);
275
-
276
- return zone;
277
- }
278
-
279
- /**
280
- * call-seq:
281
- * Time.default_zone -> 'GMT'
282
- */
283
- VALUE rb_Time_singleton_get_default_zone(VALUE self)
284
- {
285
- UChar * timeZone = ALLOC_N(UChar, 64);
286
- int32_t timeZoneLen;
287
- UErrorCode status = U_ZERO_ERROR;
288
-
289
- timeZoneLen = ucal_getDefaultTimeZone(timeZone, 2, &status);
290
- if (status == U_BUFFER_OVERFLOW_ERROR) {
291
- status = U_ZERO_ERROR;
292
- REALLOC_N(timeZone, UChar, timeZoneLen);
293
- ucal_getDefaultTimeZone(timeZone, timeZoneLen, &status);
294
- }
295
- RAISE_ON_ERROR(status);
296
-
297
- return u_strToRString(timeZone, timeZoneLen);
298
- }
299
-
300
- /**
301
- * call-seq:
302
- * 23874.localize(:date => :short) => 23.874
303
- */
304
- VALUE rb_Time_singleton_pattern(int argc, VALUE *argv, VALUE self)
305
- {
306
- VALUE options;
307
- UDateFormatStyle dateStyle = UDAT_DEFAULT, timeStyle = UDAT_DEFAULT;
308
- char *locale = NULL;
309
-
310
- UDateFormat *format;
311
- UErrorCode status = U_ZERO_ERROR;
312
-
313
- UChar * pattern = ALLOC_N(UChar, 64);
314
- int32_t patternLen;
315
-
316
- /* arguments */
317
- rb_scan_args(argc, argv, "01", &options);
318
- if (options != Qnil) {
319
- VALUE rb_locale;
320
-
321
- Check_Type(options, T_HASH);
322
- /* date and time style */
323
- dateStyle = getStyle(options, "date");
324
- timeStyle = getStyle(options, "time");
325
- /* locale */
326
- rb_locale = rb_hash_aref(options, ID2SYM(rb_intern("locale")));
327
- if (rb_locale != Qnil) {
328
- locale = StringValuePtr(rb_locale);
329
- }
330
- }
331
- /* formatter */
332
- status = U_ZERO_ERROR;
333
- format = udat_open(timeStyle, dateStyle, locale, NULL, 0, NULL, 0, &status);
334
- RAISE_ON_ERROR(status);
335
- /* pattern */
336
- patternLen = udat_toPattern(format, 0, pattern, 64, &status);
337
- if (status == U_BUFFER_OVERFLOW_ERROR) {
338
- status = U_ZERO_ERROR;
339
- REALLOC_N(pattern, UChar, patternLen);
340
- udat_toPattern(format, 0, pattern, 64, &status);
341
- }
342
- RAISE_ON_ERROR(status);
343
- /* free */
344
- udat_close(format);
345
-
346
- return u_strToRString(pattern, patternLen);
347
- }
348
-
349
- /**
350
- * call-seq:
351
- * 23874.localize(:date => :short) => 23.874
352
- */
353
- VALUE rb_Time_singleton_week_start(int argc, VALUE *argv, VALUE self)
354
- {
355
- VALUE options;
356
- char * locale = NULL;
357
- UErrorCode status = U_ZERO_ERROR;
358
- UCalendar * calendar;
359
- int32_t result;
360
-
361
- /* arguments */
362
- rb_scan_args(argc, argv, "01", &options);
363
- if (options != Qnil) {
364
- VALUE rb_locale;
365
-
366
- Check_Type(options, T_HASH);
367
- /* locale */
368
- rb_locale = rb_hash_aref(options, ID2SYM(rb_intern("locale")));
369
- if (rb_locale != Qnil) {
370
- locale = StringValuePtr(rb_locale);
371
- }
372
- }
373
- /* calendar */
374
- calendar = ucal_open(NULL, 0, locale, UCAL_GREGORIAN, &status);
375
- RAISE_ON_ERROR(status);
376
- /* attribute */
377
- result = ucal_getAttribute(calendar, UCAL_FIRST_DAY_OF_WEEK);
378
- ucal_close(calendar);
379
-
380
- return INT2NUM(result);
381
- }
382
-
383
- void Init_ICU_Time(void)
384
- {
385
- rb_define_method(rb_cTime, "localize", rb_Time_localize, -1);
386
- rb_define_singleton_method(rb_cTime, "zones", rb_Time_singleton_zones, -1);
387
- rb_define_singleton_method(rb_cTime, "default_zone=", rb_Time_singleton_set_default_zone, 1);
388
- rb_define_singleton_method(rb_cTime, "default_zone", rb_Time_singleton_get_default_zone, 0);
389
- rb_define_singleton_method(rb_cTime, "pattern", rb_Time_singleton_pattern, -1);
390
- rb_define_singleton_method(rb_cTime, "week_start", rb_Time_singleton_week_start, -1);
391
- }