OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 11 matching lines...) Expand all Loading... |
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 // limitations under the License. | 27 // limitations under the License. |
28 | 28 |
29 #include "i18n.h" | 29 #include "i18n.h" |
30 | 30 |
31 #include "unicode/calendar.h" | 31 #include "unicode/calendar.h" |
| 32 #include "unicode/coll.h" |
32 #include "unicode/curramt.h" | 33 #include "unicode/curramt.h" |
33 #include "unicode/dcfmtsym.h" | 34 #include "unicode/dcfmtsym.h" |
34 #include "unicode/decimfmt.h" | 35 #include "unicode/decimfmt.h" |
35 #include "unicode/dtfmtsym.h" | 36 #include "unicode/dtfmtsym.h" |
36 #include "unicode/dtptngen.h" | 37 #include "unicode/dtptngen.h" |
37 #include "unicode/locid.h" | 38 #include "unicode/locid.h" |
38 #include "unicode/numfmt.h" | 39 #include "unicode/numfmt.h" |
39 #include "unicode/numsys.h" | 40 #include "unicode/numsys.h" |
40 #include "unicode/smpdtfmt.h" | 41 #include "unicode/smpdtfmt.h" |
41 #include "unicode/timezone.h" | 42 #include "unicode/timezone.h" |
42 #include "unicode/uchar.h" | 43 #include "unicode/uchar.h" |
| 44 #include "unicode/ucol.h" |
43 #include "unicode/ucurr.h" | 45 #include "unicode/ucurr.h" |
44 #include "unicode/unum.h" | 46 #include "unicode/unum.h" |
45 #include "unicode/uversion.h" | 47 #include "unicode/uversion.h" |
46 | 48 |
47 namespace v8 { | 49 namespace v8 { |
48 namespace internal { | 50 namespace internal { |
49 | 51 |
50 namespace { | 52 namespace { |
51 | 53 |
52 bool ExtractStringSetting(Isolate* isolate, | 54 bool ExtractStringSetting(Isolate* isolate, |
(...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
498 // This would never happen, since we got the locale from ICU. | 500 // This would never happen, since we got the locale from ICU. |
499 JSObject::SetProperty( | 501 JSObject::SetProperty( |
500 resolved, | 502 resolved, |
501 isolate->factory()->NewStringFromAscii(CStrVector("locale")), | 503 isolate->factory()->NewStringFromAscii(CStrVector("locale")), |
502 isolate->factory()->NewStringFromAscii(CStrVector("und")), | 504 isolate->factory()->NewStringFromAscii(CStrVector("und")), |
503 NONE, | 505 NONE, |
504 kNonStrictMode); | 506 kNonStrictMode); |
505 } | 507 } |
506 } | 508 } |
507 | 509 |
| 510 |
| 511 icu::Collator* CreateICUCollator( |
| 512 Isolate* isolate, |
| 513 const icu::Locale& icu_locale, |
| 514 Handle<JSObject> options) { |
| 515 // Make collator from options. |
| 516 icu::Collator* collator = NULL; |
| 517 UErrorCode status = U_ZERO_ERROR; |
| 518 collator = icu::Collator::createInstance(icu_locale, status); |
| 519 |
| 520 if (U_FAILURE(status)) { |
| 521 delete collator; |
| 522 return NULL; |
| 523 } |
| 524 |
| 525 // Set flags first, and then override them with sensitivity if necessary. |
| 526 bool numeric; |
| 527 if (ExtractBooleanSetting(isolate, options, "numeric", &numeric)) { |
| 528 collator->setAttribute( |
| 529 UCOL_NUMERIC_COLLATION, numeric ? UCOL_ON : UCOL_OFF, status); |
| 530 } |
| 531 |
| 532 // Normalization is always on, by the spec. We are free to optimize |
| 533 // if the strings are already normalized (but we don't have a way to tell |
| 534 // that right now). |
| 535 collator->setAttribute(UCOL_NORMALIZATION_MODE, UCOL_ON, status); |
| 536 |
| 537 icu::UnicodeString case_first; |
| 538 if (ExtractStringSetting(isolate, options, "caseFirst", &case_first)) { |
| 539 if (case_first == UNICODE_STRING_SIMPLE("upper")) { |
| 540 collator->setAttribute(UCOL_CASE_FIRST, UCOL_UPPER_FIRST, status); |
| 541 } else if (case_first == UNICODE_STRING_SIMPLE("lower")) { |
| 542 collator->setAttribute(UCOL_CASE_FIRST, UCOL_LOWER_FIRST, status); |
| 543 } else { |
| 544 // Default (false/off). |
| 545 collator->setAttribute(UCOL_CASE_FIRST, UCOL_OFF, status); |
| 546 } |
| 547 } |
| 548 |
| 549 icu::UnicodeString sensitivity; |
| 550 if (ExtractStringSetting(isolate, options, "sensitivity", &sensitivity)) { |
| 551 if (sensitivity == UNICODE_STRING_SIMPLE("base")) { |
| 552 collator->setStrength(icu::Collator::PRIMARY); |
| 553 } else if (sensitivity == UNICODE_STRING_SIMPLE("accent")) { |
| 554 collator->setStrength(icu::Collator::SECONDARY); |
| 555 } else if (sensitivity == UNICODE_STRING_SIMPLE("case")) { |
| 556 collator->setStrength(icu::Collator::PRIMARY); |
| 557 collator->setAttribute(UCOL_CASE_LEVEL, UCOL_ON, status); |
| 558 } else { |
| 559 // variant (default) |
| 560 collator->setStrength(icu::Collator::TERTIARY); |
| 561 } |
| 562 } |
| 563 |
| 564 bool ignore; |
| 565 if (ExtractBooleanSetting(isolate, options, "ignorePunctuation", &ignore)) { |
| 566 if (ignore) { |
| 567 collator->setAttribute(UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, status); |
| 568 } |
| 569 } |
| 570 |
| 571 return collator; |
| 572 } |
| 573 |
| 574 |
| 575 void SetResolvedCollatorSettings(Isolate* isolate, |
| 576 const icu::Locale& icu_locale, |
| 577 icu::Collator* collator, |
| 578 Handle<JSObject> resolved) { |
| 579 UErrorCode status = U_ZERO_ERROR; |
| 580 |
| 581 JSObject::SetProperty( |
| 582 resolved, |
| 583 isolate->factory()->NewStringFromAscii(CStrVector("numeric")), |
| 584 isolate->factory()->ToBoolean( |
| 585 collator->getAttribute(UCOL_NUMERIC_COLLATION, status) == UCOL_ON), |
| 586 NONE, |
| 587 kNonStrictMode); |
| 588 |
| 589 switch (collator->getAttribute(UCOL_CASE_FIRST, status)) { |
| 590 case UCOL_LOWER_FIRST: |
| 591 JSObject::SetProperty( |
| 592 resolved, |
| 593 isolate->factory()->NewStringFromAscii(CStrVector("caseFirst")), |
| 594 isolate->factory()->NewStringFromAscii(CStrVector("lower")), |
| 595 NONE, |
| 596 kNonStrictMode); |
| 597 break; |
| 598 case UCOL_UPPER_FIRST: |
| 599 JSObject::SetProperty( |
| 600 resolved, |
| 601 isolate->factory()->NewStringFromAscii(CStrVector("caseFirst")), |
| 602 isolate->factory()->NewStringFromAscii(CStrVector("upper")), |
| 603 NONE, |
| 604 kNonStrictMode); |
| 605 break; |
| 606 default: |
| 607 JSObject::SetProperty( |
| 608 resolved, |
| 609 isolate->factory()->NewStringFromAscii(CStrVector("caseFirst")), |
| 610 isolate->factory()->NewStringFromAscii(CStrVector("false")), |
| 611 NONE, |
| 612 kNonStrictMode); |
| 613 } |
| 614 |
| 615 switch (collator->getAttribute(UCOL_STRENGTH, status)) { |
| 616 case UCOL_PRIMARY: { |
| 617 JSObject::SetProperty( |
| 618 resolved, |
| 619 isolate->factory()->NewStringFromAscii(CStrVector("strength")), |
| 620 isolate->factory()->NewStringFromAscii(CStrVector("primary")), |
| 621 NONE, |
| 622 kNonStrictMode); |
| 623 |
| 624 // case level: true + s1 -> case, s1 -> base. |
| 625 if (UCOL_ON == collator->getAttribute(UCOL_CASE_LEVEL, status)) { |
| 626 JSObject::SetProperty( |
| 627 resolved, |
| 628 isolate->factory()->NewStringFromAscii(CStrVector("sensitivity")), |
| 629 isolate->factory()->NewStringFromAscii(CStrVector("case")), |
| 630 NONE, |
| 631 kNonStrictMode); |
| 632 } else { |
| 633 JSObject::SetProperty( |
| 634 resolved, |
| 635 isolate->factory()->NewStringFromAscii(CStrVector("sensitivity")), |
| 636 isolate->factory()->NewStringFromAscii(CStrVector("base")), |
| 637 NONE, |
| 638 kNonStrictMode); |
| 639 } |
| 640 break; |
| 641 } |
| 642 case UCOL_SECONDARY: |
| 643 JSObject::SetProperty( |
| 644 resolved, |
| 645 isolate->factory()->NewStringFromAscii(CStrVector("strength")), |
| 646 isolate->factory()->NewStringFromAscii(CStrVector("secondary")), |
| 647 NONE, |
| 648 kNonStrictMode); |
| 649 JSObject::SetProperty( |
| 650 resolved, |
| 651 isolate->factory()->NewStringFromAscii(CStrVector("sensitivity")), |
| 652 isolate->factory()->NewStringFromAscii(CStrVector("accent")), |
| 653 NONE, |
| 654 kNonStrictMode); |
| 655 break; |
| 656 case UCOL_TERTIARY: |
| 657 JSObject::SetProperty( |
| 658 resolved, |
| 659 isolate->factory()->NewStringFromAscii(CStrVector("strength")), |
| 660 isolate->factory()->NewStringFromAscii(CStrVector("tertiary")), |
| 661 NONE, |
| 662 kNonStrictMode); |
| 663 JSObject::SetProperty( |
| 664 resolved, |
| 665 isolate->factory()->NewStringFromAscii(CStrVector("sensitivity")), |
| 666 isolate->factory()->NewStringFromAscii(CStrVector("variant")), |
| 667 NONE, |
| 668 kNonStrictMode); |
| 669 break; |
| 670 case UCOL_QUATERNARY: |
| 671 // We shouldn't get quaternary and identical from ICU, but if we do |
| 672 // put them into variant. |
| 673 JSObject::SetProperty( |
| 674 resolved, |
| 675 isolate->factory()->NewStringFromAscii(CStrVector("strength")), |
| 676 isolate->factory()->NewStringFromAscii(CStrVector("quaternary")), |
| 677 NONE, |
| 678 kNonStrictMode); |
| 679 JSObject::SetProperty( |
| 680 resolved, |
| 681 isolate->factory()->NewStringFromAscii(CStrVector("sensitivity")), |
| 682 isolate->factory()->NewStringFromAscii(CStrVector("variant")), |
| 683 NONE, |
| 684 kNonStrictMode); |
| 685 break; |
| 686 default: |
| 687 JSObject::SetProperty( |
| 688 resolved, |
| 689 isolate->factory()->NewStringFromAscii(CStrVector("strength")), |
| 690 isolate->factory()->NewStringFromAscii(CStrVector("identical")), |
| 691 NONE, |
| 692 kNonStrictMode); |
| 693 JSObject::SetProperty( |
| 694 resolved, |
| 695 isolate->factory()->NewStringFromAscii(CStrVector("sensitivity")), |
| 696 isolate->factory()->NewStringFromAscii(CStrVector("variant")), |
| 697 NONE, |
| 698 kNonStrictMode); |
| 699 } |
| 700 |
| 701 JSObject::SetProperty( |
| 702 resolved, |
| 703 isolate->factory()->NewStringFromAscii(CStrVector("ignorePunctuation")), |
| 704 isolate->factory()->ToBoolean(collator->getAttribute( |
| 705 UCOL_ALTERNATE_HANDLING, status) == UCOL_SHIFTED), |
| 706 NONE, |
| 707 kNonStrictMode); |
| 708 |
| 709 // Set the locale |
| 710 char result[ULOC_FULLNAME_CAPACITY]; |
| 711 status = U_ZERO_ERROR; |
| 712 uloc_toLanguageTag( |
| 713 icu_locale.getName(), result, ULOC_FULLNAME_CAPACITY, FALSE, &status); |
| 714 if (U_SUCCESS(status)) { |
| 715 JSObject::SetProperty( |
| 716 resolved, |
| 717 isolate->factory()->NewStringFromAscii(CStrVector("locale")), |
| 718 isolate->factory()->NewStringFromAscii(CStrVector(result)), |
| 719 NONE, |
| 720 kNonStrictMode); |
| 721 } else { |
| 722 // This would never happen, since we got the locale from ICU. |
| 723 JSObject::SetProperty( |
| 724 resolved, |
| 725 isolate->factory()->NewStringFromAscii(CStrVector("locale")), |
| 726 isolate->factory()->NewStringFromAscii(CStrVector("und")), |
| 727 NONE, |
| 728 kNonStrictMode); |
| 729 } |
| 730 } |
| 731 |
508 } // namespace | 732 } // namespace |
509 | 733 |
510 | 734 |
511 // static | 735 // static |
512 Handle<ObjectTemplateInfo> I18N::GetTemplate(Isolate* isolate) { | 736 Handle<ObjectTemplateInfo> I18N::GetTemplate(Isolate* isolate) { |
513 return GetEternal<1, i::EternalHandles::I18N_TEMPLATE_ONE>(isolate); | 737 return GetEternal<1, i::EternalHandles::I18N_TEMPLATE_ONE>(isolate); |
514 } | 738 } |
515 | 739 |
516 | 740 |
517 // static | 741 // static |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
639 Persistent<v8::Object>* object, | 863 Persistent<v8::Object>* object, |
640 void* param) { | 864 void* param) { |
641 // First delete the hidden C++ object. | 865 // First delete the hidden C++ object. |
642 delete reinterpret_cast<icu::DecimalFormat*>(Handle<JSObject>::cast( | 866 delete reinterpret_cast<icu::DecimalFormat*>(Handle<JSObject>::cast( |
643 v8::Utils::OpenPersistent(object))->GetInternalField(0)); | 867 v8::Utils::OpenPersistent(object))->GetInternalField(0)); |
644 | 868 |
645 // Then dispose of the persistent handle to JS object. | 869 // Then dispose of the persistent handle to JS object. |
646 object->Dispose(isolate); | 870 object->Dispose(isolate); |
647 } | 871 } |
648 | 872 |
| 873 |
| 874 icu::Collator* Collator::InitializeCollator( |
| 875 Isolate* isolate, |
| 876 Handle<String> locale, |
| 877 Handle<JSObject> options, |
| 878 Handle<JSObject> resolved) { |
| 879 // Convert BCP47 into ICU locale format. |
| 880 UErrorCode status = U_ZERO_ERROR; |
| 881 icu::Locale icu_locale; |
| 882 char icu_result[ULOC_FULLNAME_CAPACITY]; |
| 883 int icu_length = 0; |
| 884 v8::String::Utf8Value bcp47_locale(v8::Utils::ToLocal(locale)); |
| 885 if (bcp47_locale.length() != 0) { |
| 886 uloc_forLanguageTag(*bcp47_locale, icu_result, ULOC_FULLNAME_CAPACITY, |
| 887 &icu_length, &status); |
| 888 if (U_FAILURE(status) || icu_length == 0) { |
| 889 return NULL; |
| 890 } |
| 891 icu_locale = icu::Locale(icu_result); |
| 892 } |
| 893 |
| 894 icu::Collator* collator = CreateICUCollator(isolate, icu_locale, options); |
| 895 if (!collator) { |
| 896 // Remove extensions and try again. |
| 897 icu::Locale no_extension_locale(icu_locale.getBaseName()); |
| 898 collator = CreateICUCollator(isolate, no_extension_locale, options); |
| 899 |
| 900 // Set resolved settings (pattern, numbering system). |
| 901 SetResolvedCollatorSettings( |
| 902 isolate, no_extension_locale, collator, resolved); |
| 903 } else { |
| 904 SetResolvedCollatorSettings(isolate, icu_locale, collator, resolved); |
| 905 } |
| 906 |
| 907 return collator; |
| 908 } |
| 909 |
| 910 |
| 911 icu::Collator* Collator::UnpackCollator(Isolate* isolate, |
| 912 Handle<JSObject> obj) { |
| 913 if (obj->HasLocalProperty(*isolate->factory()->NewStringFromAscii( |
| 914 CStrVector("collator")))) { |
| 915 return reinterpret_cast<icu::Collator*>(obj->GetInternalField(0)); |
| 916 } |
| 917 |
| 918 return NULL; |
| 919 } |
| 920 |
| 921 |
| 922 void Collator::DeleteCollator(v8::Isolate* isolate, |
| 923 Persistent<v8::Object>* object, |
| 924 void* param) { |
| 925 // First delete the hidden C++ object. |
| 926 delete reinterpret_cast<icu::Collator*>(Handle<JSObject>::cast( |
| 927 v8::Utils::OpenPersistent(object))->GetInternalField(0)); |
| 928 |
| 929 // Then dispose of the persistent handle to JS object. |
| 930 object->Dispose(isolate); |
| 931 } |
| 932 |
649 } } // namespace v8::internal | 933 } } // namespace v8::internal |
OLD | NEW |