icu 0.9.1 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
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
- }