1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 // limitations under the License.
31 #include "unicode/calendar.h"
32 #include "unicode/coll.h"
33 #include "unicode/curramt.h"
34 #include "unicode/dcfmtsym.h"
35 #include "unicode/decimfmt.h"
36 #include "unicode/dtfmtsym.h"
37 #include "unicode/dtptngen.h"
38 #include "unicode/locid.h"
39 #include "unicode/numfmt.h"
40 #include "unicode/numsys.h"
41 #include "unicode/smpdtfmt.h"
42 #include "unicode/timezone.h"
43 #include "unicode/uchar.h"
44 #include "unicode/ucol.h"
45 #include "unicode/ucurr.h"
46 #include "unicode/unum.h"
47 #include "unicode/uversion.h"
54 bool ExtractStringSetting(Isolate* isolate,
55 Handle<JSObject> options,
57 icu::UnicodeString* setting) {
58 Handle<String> str = isolate->factory()->NewStringFromAscii(CStrVector(key));
59 MaybeObject* maybe_object = options->GetProperty(*str);
61 if (maybe_object->ToObject(&object) && object->IsString()) {
62 v8::String::Utf8Value utf8_string(
63 v8::Utils::ToLocal(Handle<String>(String::cast(object))));
64 *setting = icu::UnicodeString::fromUTF8(*utf8_string);
71 bool ExtractIntegerSetting(Isolate* isolate,
72 Handle<JSObject> options,
75 Handle<String> str = isolate->factory()->NewStringFromAscii(CStrVector(key));
76 MaybeObject* maybe_object = options->GetProperty(*str);
78 if (maybe_object->ToObject(&object) && object->IsNumber()) {
79 object->ToInt32(value);
86 bool ExtractBooleanSetting(Isolate* isolate,
87 Handle<JSObject> options,
90 Handle<String> str = isolate->factory()->NewStringFromAscii(CStrVector(key));
91 MaybeObject* maybe_object = options->GetProperty(*str);
93 if (maybe_object->ToObject(&object) && object->IsBoolean()) {
94 *value = object->BooleanValue();
101 icu::SimpleDateFormat* CreateICUDateFormat(
103 const icu::Locale& icu_locale,
104 Handle<JSObject> options) {
105 // Create time zone as specified by the user. We have to re-create time zone
106 // since calendar takes ownership.
107 icu::TimeZone* tz = NULL;
108 icu::UnicodeString timezone;
109 if (ExtractStringSetting(isolate, options, "timeZone", &timezone)) {
110 tz = icu::TimeZone::createTimeZone(timezone);
112 tz = icu::TimeZone::createDefault();
115 // Create a calendar using locale, and apply time zone to it.
116 UErrorCode status = U_ZERO_ERROR;
117 icu::Calendar* calendar =
118 icu::Calendar::createInstance(tz, icu_locale, status);
120 // Make formatter from skeleton. Calendar and numbering system are added
121 // to the locale as Unicode extension (if they were specified at all).
122 icu::SimpleDateFormat* date_format = NULL;
123 icu::UnicodeString skeleton;
124 if (ExtractStringSetting(isolate, options, "skeleton", &skeleton)) {
125 icu::DateTimePatternGenerator* generator =
126 icu::DateTimePatternGenerator::createInstance(icu_locale, status);
127 icu::UnicodeString pattern;
128 if (U_SUCCESS(status)) {
129 pattern = generator->getBestPattern(skeleton, status);
133 date_format = new icu::SimpleDateFormat(pattern, icu_locale, status);
134 if (U_SUCCESS(status)) {
135 date_format->adoptCalendar(calendar);
139 if (U_FAILURE(status)) {
149 void SetResolvedDateSettings(Isolate* isolate,
150 const icu::Locale& icu_locale,
151 icu::SimpleDateFormat* date_format,
152 Handle<JSObject> resolved) {
153 UErrorCode status = U_ZERO_ERROR;
154 icu::UnicodeString pattern;
155 date_format->toPattern(pattern);
156 JSObject::SetProperty(
158 isolate->factory()->NewStringFromAscii(CStrVector("pattern")),
159 isolate->factory()->NewStringFromTwoByte(
160 Vector<const uint16_t>(
161 reinterpret_cast<const uint16_t*>(pattern.getBuffer()),
166 // Set time zone and calendar.
167 const icu::Calendar* calendar = date_format->getCalendar();
168 const char* calendar_name = calendar->getType();
169 JSObject::SetProperty(
171 isolate->factory()->NewStringFromAscii(CStrVector("calendar")),
172 isolate->factory()->NewStringFromAscii(CStrVector(calendar_name)),
176 const icu::TimeZone& tz = calendar->getTimeZone();
177 icu::UnicodeString time_zone;
180 icu::UnicodeString canonical_time_zone;
181 icu::TimeZone::getCanonicalID(time_zone, canonical_time_zone, status);
182 if (U_SUCCESS(status)) {
183 if (canonical_time_zone == UNICODE_STRING_SIMPLE("Etc/GMT")) {
184 JSObject::SetProperty(
186 isolate->factory()->NewStringFromAscii(CStrVector("timeZone")),
187 isolate->factory()->NewStringFromAscii(CStrVector("UTC")),
191 JSObject::SetProperty(
193 isolate->factory()->NewStringFromAscii(CStrVector("timeZone")),
194 isolate->factory()->NewStringFromTwoByte(
195 Vector<const uint16_t>(
196 reinterpret_cast<const uint16_t*>(
197 canonical_time_zone.getBuffer()),
198 canonical_time_zone.length())),
204 // Ugly hack. ICU doesn't expose numbering system in any way, so we have
205 // to assume that for given locale NumberingSystem constructor produces the
206 // same digits as NumberFormat/Calendar would.
207 status = U_ZERO_ERROR;
208 icu::NumberingSystem* numbering_system =
209 icu::NumberingSystem::createInstance(icu_locale, status);
210 if (U_SUCCESS(status)) {
211 const char* ns = numbering_system->getName();
212 JSObject::SetProperty(
214 isolate->factory()->NewStringFromAscii(CStrVector("numberingSystem")),
215 isolate->factory()->NewStringFromAscii(CStrVector(ns)),
219 JSObject::SetProperty(
221 isolate->factory()->NewStringFromAscii(CStrVector("numberingSystem")),
222 isolate->factory()->undefined_value(),
226 delete numbering_system;
229 char result[ULOC_FULLNAME_CAPACITY];
230 status = U_ZERO_ERROR;
232 icu_locale.getName(), result, ULOC_FULLNAME_CAPACITY, FALSE, &status);
233 if (U_SUCCESS(status)) {
234 JSObject::SetProperty(
236 isolate->factory()->NewStringFromAscii(CStrVector("locale")),
237 isolate->factory()->NewStringFromAscii(CStrVector(result)),
241 // This would never happen, since we got the locale from ICU.
242 JSObject::SetProperty(
244 isolate->factory()->NewStringFromAscii(CStrVector("locale")),
245 isolate->factory()->NewStringFromAscii(CStrVector("und")),
252 template<int internal_fields, EternalHandles::SingletonHandle field>
253 Handle<ObjectTemplateInfo> GetEternal(Isolate* isolate) {
254 if (isolate->eternal_handles()->Exists(field)) {
255 return Handle<ObjectTemplateInfo>::cast(
256 isolate->eternal_handles()->GetSingleton(field));
258 v8::Local<v8::ObjectTemplate> raw_template(v8::ObjectTemplate::New());
259 raw_template->SetInternalFieldCount(internal_fields);
260 return Handle<ObjectTemplateInfo>::cast(
261 isolate->eternal_handles()->CreateSingleton(
263 *v8::Utils::OpenHandle(*raw_template),
268 icu::DecimalFormat* CreateICUNumberFormat(
270 const icu::Locale& icu_locale,
271 Handle<JSObject> options) {
272 // Make formatter from options. Numbering system is added
273 // to the locale as Unicode extension (if it was specified at all).
274 UErrorCode status = U_ZERO_ERROR;
275 icu::DecimalFormat* number_format = NULL;
276 icu::UnicodeString style;
277 icu::UnicodeString currency;
278 if (ExtractStringSetting(isolate, options, "style", &style)) {
279 if (style == UNICODE_STRING_SIMPLE("currency")) {
280 icu::UnicodeString display;
281 ExtractStringSetting(isolate, options, "currency", ¤cy);
282 ExtractStringSetting(isolate, options, "currencyDisplay", &display);
284 #if (U_ICU_VERSION_MAJOR_NUM == 4) && (U_ICU_VERSION_MINOR_NUM <= 6)
285 icu::NumberFormat::EStyles format_style;
286 if (display == UNICODE_STRING_SIMPLE("code")) {
287 format_style = icu::NumberFormat::kIsoCurrencyStyle;
288 } else if (display == UNICODE_STRING_SIMPLE("name")) {
289 format_style = icu::NumberFormat::kPluralCurrencyStyle;
291 format_style = icu::NumberFormat::kCurrencyStyle;
293 #else // ICU version is 4.8 or above (we ignore versions below 4.0).
294 UNumberFormatStyle format_style;
295 if (display == UNICODE_STRING_SIMPLE("code")) {
296 format_style = UNUM_CURRENCY_ISO;
297 } else if (display == UNICODE_STRING_SIMPLE("name")) {
298 format_style = UNUM_CURRENCY_PLURAL;
300 format_style = UNUM_CURRENCY;
304 number_format = static_cast<icu::DecimalFormat*>(
305 icu::NumberFormat::createInstance(icu_locale, format_style, status));
306 } else if (style == UNICODE_STRING_SIMPLE("percent")) {
307 number_format = static_cast<icu::DecimalFormat*>(
308 icu::NumberFormat::createPercentInstance(icu_locale, status));
309 if (U_FAILURE(status)) {
310 delete number_format;
313 // Make sure 1.1% doesn't go into 2%.
314 number_format->setMinimumFractionDigits(1);
316 // Make a decimal instance by default.
317 number_format = static_cast<icu::DecimalFormat*>(
318 icu::NumberFormat::createInstance(icu_locale, status));
322 if (U_FAILURE(status)) {
323 delete number_format;
328 if (!currency.isEmpty()) {
329 number_format->setCurrency(currency.getBuffer(), status);
333 if (ExtractIntegerSetting(
334 isolate, options, "minimumIntegerDigits", &digits)) {
335 number_format->setMinimumIntegerDigits(digits);
338 if (ExtractIntegerSetting(
339 isolate, options, "minimumFractionDigits", &digits)) {
340 number_format->setMinimumFractionDigits(digits);
343 if (ExtractIntegerSetting(
344 isolate, options, "maximumFractionDigits", &digits)) {
345 number_format->setMaximumFractionDigits(digits);
348 bool significant_digits_used = false;
349 if (ExtractIntegerSetting(
350 isolate, options, "minimumSignificantDigits", &digits)) {
351 number_format->setMinimumSignificantDigits(digits);
352 significant_digits_used = true;
355 if (ExtractIntegerSetting(
356 isolate, options, "maximumSignificantDigits", &digits)) {
357 number_format->setMaximumSignificantDigits(digits);
358 significant_digits_used = true;
361 number_format->setSignificantDigitsUsed(significant_digits_used);
364 if (ExtractBooleanSetting(isolate, options, "useGrouping", &grouping)) {
365 number_format->setGroupingUsed(grouping);
368 // Set rounding mode.
369 number_format->setRoundingMode(icu::DecimalFormat::kRoundHalfUp);
371 return number_format;
375 void SetResolvedNumberSettings(Isolate* isolate,
376 const icu::Locale& icu_locale,
377 icu::DecimalFormat* number_format,
378 Handle<JSObject> resolved) {
379 icu::UnicodeString pattern;
380 number_format->toPattern(pattern);
381 JSObject::SetProperty(
383 isolate->factory()->NewStringFromAscii(CStrVector("pattern")),
384 isolate->factory()->NewStringFromTwoByte(
385 Vector<const uint16_t>(
386 reinterpret_cast<const uint16_t*>(pattern.getBuffer()),
391 // Set resolved currency code in options.currency if not empty.
392 icu::UnicodeString currency(number_format->getCurrency());
393 if (!currency.isEmpty()) {
394 JSObject::SetProperty(
396 isolate->factory()->NewStringFromAscii(CStrVector("currency")),
397 isolate->factory()->NewStringFromTwoByte(
398 Vector<const uint16_t>(
399 reinterpret_cast<const uint16_t*>(currency.getBuffer()),
405 // Ugly hack. ICU doesn't expose numbering system in any way, so we have
406 // to assume that for given locale NumberingSystem constructor produces the
407 // same digits as NumberFormat/Calendar would.
408 UErrorCode status = U_ZERO_ERROR;
409 icu::NumberingSystem* numbering_system =
410 icu::NumberingSystem::createInstance(icu_locale, status);
411 if (U_SUCCESS(status)) {
412 const char* ns = numbering_system->getName();
413 JSObject::SetProperty(
415 isolate->factory()->NewStringFromAscii(CStrVector("numberingSystem")),
416 isolate->factory()->NewStringFromAscii(CStrVector(ns)),
420 JSObject::SetProperty(
422 isolate->factory()->NewStringFromAscii(CStrVector("numberingSystem")),
423 isolate->factory()->undefined_value(),
427 delete numbering_system;
429 JSObject::SetProperty(
431 isolate->factory()->NewStringFromAscii(CStrVector("useGrouping")),
432 isolate->factory()->ToBoolean(number_format->isGroupingUsed()),
436 JSObject::SetProperty(
438 isolate->factory()->NewStringFromAscii(
439 CStrVector("minimumIntegerDigits")),
440 isolate->factory()->NewNumberFromInt(
441 number_format->getMinimumIntegerDigits()),
445 JSObject::SetProperty(
447 isolate->factory()->NewStringFromAscii(
448 CStrVector("minimumFractionDigits")),
449 isolate->factory()->NewNumberFromInt(
450 number_format->getMinimumFractionDigits()),
454 JSObject::SetProperty(
456 isolate->factory()->NewStringFromAscii(
457 CStrVector("maximumFractionDigits")),
458 isolate->factory()->NewNumberFromInt(
459 number_format->getMaximumFractionDigits()),
463 Handle<String> key = isolate->factory()->NewStringFromAscii(
464 CStrVector("minimumSignificantDigits"));
465 if (resolved->HasLocalProperty(*key)) {
466 JSObject::SetProperty(
468 isolate->factory()->NewStringFromAscii(
469 CStrVector("minimumSignificantDigits")),
470 isolate->factory()->NewNumberFromInt(
471 number_format->getMinimumSignificantDigits()),
476 key = isolate->factory()->NewStringFromAscii(
477 CStrVector("maximumSignificantDigits"));
478 if (resolved->HasLocalProperty(*key)) {
479 JSObject::SetProperty(
481 isolate->factory()->NewStringFromAscii(
482 CStrVector("maximumSignificantDigits")),
483 isolate->factory()->NewNumberFromInt(
484 number_format->getMaximumSignificantDigits()),
490 char result[ULOC_FULLNAME_CAPACITY];
491 status = U_ZERO_ERROR;
493 icu_locale.getName(), result, ULOC_FULLNAME_CAPACITY, FALSE, &status);
494 if (U_SUCCESS(status)) {
495 JSObject::SetProperty(
497 isolate->factory()->NewStringFromAscii(CStrVector("locale")),
498 isolate->factory()->NewStringFromAscii(CStrVector(result)),
502 // This would never happen, since we got the locale from ICU.
503 JSObject::SetProperty(
505 isolate->factory()->NewStringFromAscii(CStrVector("locale")),
506 isolate->factory()->NewStringFromAscii(CStrVector("und")),
513 icu::Collator* CreateICUCollator(
515 const icu::Locale& icu_locale,
516 Handle<JSObject> options) {
517 // Make collator from options.
518 icu::Collator* collator = NULL;
519 UErrorCode status = U_ZERO_ERROR;
520 collator = icu::Collator::createInstance(icu_locale, status);
522 if (U_FAILURE(status)) {
527 // Set flags first, and then override them with sensitivity if necessary.
529 if (ExtractBooleanSetting(isolate, options, "numeric", &numeric)) {
530 collator->setAttribute(
531 UCOL_NUMERIC_COLLATION, numeric ? UCOL_ON : UCOL_OFF, status);
534 // Normalization is always on, by the spec. We are free to optimize
535 // if the strings are already normalized (but we don't have a way to tell
537 collator->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_ON, status);
539 icu::UnicodeString case_first;
540 if (ExtractStringSetting(isolate, options, "caseFirst", &case_first)) {
541 if (case_first == UNICODE_STRING_SIMPLE("upper")) {
542 collator->setAttribute(UCOL_CASE_FIRST, UCOL_UPPER_FIRST, status);
543 } else if (case_first == UNICODE_STRING_SIMPLE("lower")) {
544 collator->setAttribute(UCOL_CASE_FIRST, UCOL_LOWER_FIRST, status);
546 // Default (false/off).
547 collator->setAttribute(UCOL_CASE_FIRST, UCOL_OFF, status);
551 icu::UnicodeString sensitivity;
552 if (ExtractStringSetting(isolate, options, "sensitivity", &sensitivity)) {
553 if (sensitivity == UNICODE_STRING_SIMPLE("base")) {
554 collator->setStrength(icu::Collator::PRIMARY);
555 } else if (sensitivity == UNICODE_STRING_SIMPLE("accent")) {
556 collator->setStrength(icu::Collator::SECONDARY);
557 } else if (sensitivity == UNICODE_STRING_SIMPLE("case")) {
558 collator->setStrength(icu::Collator::PRIMARY);
559 collator->setAttribute(UCOL_CASE_LEVEL, UCOL_ON, status);
562 collator->setStrength(icu::Collator::TERTIARY);
567 if (ExtractBooleanSetting(isolate, options, "ignorePunctuation", &ignore)) {
569 collator->setAttribute(UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, status);
577 void SetResolvedCollatorSettings(Isolate* isolate,
578 const icu::Locale& icu_locale,
579 icu::Collator* collator,
580 Handle<JSObject> resolved) {
581 UErrorCode status = U_ZERO_ERROR;
583 JSObject::SetProperty(
585 isolate->factory()->NewStringFromAscii(CStrVector("numeric")),
586 isolate->factory()->ToBoolean(
587 collator->getAttribute(UCOL_NUMERIC_COLLATION, status) == UCOL_ON),
591 switch (collator->getAttribute(UCOL_CASE_FIRST, status)) {
592 case UCOL_LOWER_FIRST:
593 JSObject::SetProperty(
595 isolate->factory()->NewStringFromAscii(CStrVector("caseFirst")),
596 isolate->factory()->NewStringFromAscii(CStrVector("lower")),
600 case UCOL_UPPER_FIRST:
601 JSObject::SetProperty(
603 isolate->factory()->NewStringFromAscii(CStrVector("caseFirst")),
604 isolate->factory()->NewStringFromAscii(CStrVector("upper")),
609 JSObject::SetProperty(
611 isolate->factory()->NewStringFromAscii(CStrVector("caseFirst")),
612 isolate->factory()->NewStringFromAscii(CStrVector("false")),
617 switch (collator->getAttribute(UCOL_STRENGTH, status)) {
619 JSObject::SetProperty(
621 isolate->factory()->NewStringFromAscii(CStrVector("strength")),
622 isolate->factory()->NewStringFromAscii(CStrVector("primary")),
626 // case level: true + s1 -> case, s1 -> base.
627 if (UCOL_ON == collator->getAttribute(UCOL_CASE_LEVEL, status)) {
628 JSObject::SetProperty(
630 isolate->factory()->NewStringFromAscii(CStrVector("sensitivity")),
631 isolate->factory()->NewStringFromAscii(CStrVector("case")),
635 JSObject::SetProperty(
637 isolate->factory()->NewStringFromAscii(CStrVector("sensitivity")),
638 isolate->factory()->NewStringFromAscii(CStrVector("base")),
645 JSObject::SetProperty(
647 isolate->factory()->NewStringFromAscii(CStrVector("strength")),
648 isolate->factory()->NewStringFromAscii(CStrVector("secondary")),
651 JSObject::SetProperty(
653 isolate->factory()->NewStringFromAscii(CStrVector("sensitivity")),
654 isolate->factory()->NewStringFromAscii(CStrVector("accent")),
659 JSObject::SetProperty(
661 isolate->factory()->NewStringFromAscii(CStrVector("strength")),
662 isolate->factory()->NewStringFromAscii(CStrVector("tertiary")),
665 JSObject::SetProperty(
667 isolate->factory()->NewStringFromAscii(CStrVector("sensitivity")),
668 isolate->factory()->NewStringFromAscii(CStrVector("variant")),
672 case UCOL_QUATERNARY:
673 // We shouldn't get quaternary and identical from ICU, but if we do
674 // put them into variant.
675 JSObject::SetProperty(
677 isolate->factory()->NewStringFromAscii(CStrVector("strength")),
678 isolate->factory()->NewStringFromAscii(CStrVector("quaternary")),
681 JSObject::SetProperty(
683 isolate->factory()->NewStringFromAscii(CStrVector("sensitivity")),
684 isolate->factory()->NewStringFromAscii(CStrVector("variant")),
689 JSObject::SetProperty(
691 isolate->factory()->NewStringFromAscii(CStrVector("strength")),
692 isolate->factory()->NewStringFromAscii(CStrVector("identical")),
695 JSObject::SetProperty(
697 isolate->factory()->NewStringFromAscii(CStrVector("sensitivity")),
698 isolate->factory()->NewStringFromAscii(CStrVector("variant")),
703 JSObject::SetProperty(
705 isolate->factory()->NewStringFromAscii(CStrVector("ignorePunctuation")),
706 isolate->factory()->ToBoolean(collator->getAttribute(
707 UCOL_ALTERNATE_HANDLING, status) == UCOL_SHIFTED),
712 char result[ULOC_FULLNAME_CAPACITY];
713 status = U_ZERO_ERROR;
715 icu_locale.getName(), result, ULOC_FULLNAME_CAPACITY, FALSE, &status);
716 if (U_SUCCESS(status)) {
717 JSObject::SetProperty(
719 isolate->factory()->NewStringFromAscii(CStrVector("locale")),
720 isolate->factory()->NewStringFromAscii(CStrVector(result)),
724 // This would never happen, since we got the locale from ICU.
725 JSObject::SetProperty(
727 isolate->factory()->NewStringFromAscii(CStrVector("locale")),
728 isolate->factory()->NewStringFromAscii(CStrVector("und")),
738 Handle<ObjectTemplateInfo> I18N::GetTemplate(Isolate* isolate) {
739 return GetEternal<1, i::EternalHandles::I18N_TEMPLATE_ONE>(isolate);
744 Handle<ObjectTemplateInfo> I18N::GetTemplate2(Isolate* isolate) {
745 return GetEternal<2, i::EternalHandles::I18N_TEMPLATE_TWO>(isolate);
750 icu::SimpleDateFormat* DateFormat::InitializeDateTimeFormat(
752 Handle<String> locale,
753 Handle<JSObject> options,
754 Handle<JSObject> resolved) {
755 // Convert BCP47 into ICU locale format.
756 UErrorCode status = U_ZERO_ERROR;
757 icu::Locale icu_locale;
758 char icu_result[ULOC_FULLNAME_CAPACITY];
760 v8::String::Utf8Value bcp47_locale(v8::Utils::ToLocal(locale));
761 if (bcp47_locale.length() != 0) {
762 uloc_forLanguageTag(*bcp47_locale, icu_result, ULOC_FULLNAME_CAPACITY,
763 &icu_length, &status);
764 if (U_FAILURE(status) || icu_length == 0) {
767 icu_locale = icu::Locale(icu_result);
770 icu::SimpleDateFormat* date_format = CreateICUDateFormat(
771 isolate, icu_locale, options);
773 // Remove extensions and try again.
774 icu::Locale no_extension_locale(icu_locale.getBaseName());
775 date_format = CreateICUDateFormat(isolate, no_extension_locale, options);
777 // Set resolved settings (pattern, numbering system, calendar).
778 SetResolvedDateSettings(
779 isolate, no_extension_locale, date_format, resolved);
781 SetResolvedDateSettings(isolate, icu_locale, date_format, resolved);
788 icu::SimpleDateFormat* DateFormat::UnpackDateFormat(
790 Handle<JSObject> obj) {
792 isolate->factory()->NewStringFromAscii(CStrVector("dateFormat"));
793 if (obj->HasLocalProperty(*key)) {
794 return reinterpret_cast<icu::SimpleDateFormat*>(
795 obj->GetInternalField(0));
802 void DateFormat::DeleteDateFormat(v8::Isolate* isolate,
803 Persistent<v8::Object>* object,
805 // First delete the hidden C++ object.
806 delete reinterpret_cast<icu::SimpleDateFormat*>(Handle<JSObject>::cast(
807 v8::Utils::OpenPersistent(object))->GetInternalField(0));
809 // Then dispose of the persistent handle to JS object.
810 object->Dispose(isolate);
814 icu::DecimalFormat* NumberFormat::InitializeNumberFormat(
816 Handle<String> locale,
817 Handle<JSObject> options,
818 Handle<JSObject> resolved) {
819 // Convert BCP47 into ICU locale format.
820 UErrorCode status = U_ZERO_ERROR;
821 icu::Locale icu_locale;
822 char icu_result[ULOC_FULLNAME_CAPACITY];
824 v8::String::Utf8Value bcp47_locale(v8::Utils::ToLocal(locale));
825 if (bcp47_locale.length() != 0) {
826 uloc_forLanguageTag(*bcp47_locale, icu_result, ULOC_FULLNAME_CAPACITY,
827 &icu_length, &status);
828 if (U_FAILURE(status) || icu_length == 0) {
831 icu_locale = icu::Locale(icu_result);
834 icu::DecimalFormat* number_format =
835 CreateICUNumberFormat(isolate, icu_locale, options);
836 if (!number_format) {
837 // Remove extensions and try again.
838 icu::Locale no_extension_locale(icu_locale.getBaseName());
839 number_format = CreateICUNumberFormat(
840 isolate, no_extension_locale, options);
842 // Set resolved settings (pattern, numbering system).
843 SetResolvedNumberSettings(
844 isolate, no_extension_locale, number_format, resolved);
846 SetResolvedNumberSettings(isolate, icu_locale, number_format, resolved);
849 return number_format;
853 icu::DecimalFormat* NumberFormat::UnpackNumberFormat(
855 Handle<JSObject> obj) {
857 isolate->factory()->NewStringFromAscii(CStrVector("numberFormat"));
858 if (obj->HasLocalProperty(*key)) {
859 return reinterpret_cast<icu::DecimalFormat*>(obj->GetInternalField(0));
866 void NumberFormat::DeleteNumberFormat(v8::Isolate* isolate,
867 Persistent<v8::Object>* object,
869 // First delete the hidden C++ object.
870 delete reinterpret_cast<icu::DecimalFormat*>(Handle<JSObject>::cast(
871 v8::Utils::OpenPersistent(object))->GetInternalField(0));
873 // Then dispose of the persistent handle to JS object.
874 object->Dispose(isolate);
878 icu::Collator* Collator::InitializeCollator(
880 Handle<String> locale,
881 Handle<JSObject> options,
882 Handle<JSObject> resolved) {
883 // Convert BCP47 into ICU locale format.
884 UErrorCode status = U_ZERO_ERROR;
885 icu::Locale icu_locale;
886 char icu_result[ULOC_FULLNAME_CAPACITY];
888 v8::String::Utf8Value bcp47_locale(v8::Utils::ToLocal(locale));
889 if (bcp47_locale.length() != 0) {
890 uloc_forLanguageTag(*bcp47_locale, icu_result, ULOC_FULLNAME_CAPACITY,
891 &icu_length, &status);
892 if (U_FAILURE(status) || icu_length == 0) {
895 icu_locale = icu::Locale(icu_result);
898 icu::Collator* collator = CreateICUCollator(isolate, icu_locale, options);
900 // Remove extensions and try again.
901 icu::Locale no_extension_locale(icu_locale.getBaseName());
902 collator = CreateICUCollator(isolate, no_extension_locale, options);
904 // Set resolved settings (pattern, numbering system).
905 SetResolvedCollatorSettings(
906 isolate, no_extension_locale, collator, resolved);
908 SetResolvedCollatorSettings(isolate, icu_locale, collator, resolved);
915 icu::Collator* Collator::UnpackCollator(Isolate* isolate,
916 Handle<JSObject> obj) {
918 isolate->factory()->NewStringFromAscii(CStrVector("collator"));
919 if (obj->HasLocalProperty(*key)) {
920 return reinterpret_cast<icu::Collator*>(obj->GetInternalField(0));
927 void Collator::DeleteCollator(v8::Isolate* isolate,
928 Persistent<v8::Object>* object,
930 // First delete the hidden C++ object.
931 delete reinterpret_cast<icu::Collator*>(Handle<JSObject>::cast(
932 v8::Utils::OpenPersistent(object))->GetInternalField(0));
934 // Then dispose of the persistent handle to JS object.
935 object->Dispose(isolate);
938 } } // namespace v8::internal