| OLD | NEW |
| 1 /* | 1 /* |
| 2 ********************************************************************** | 2 ********************************************************************** |
| 3 * Copyright (c) 2002-2012, International Business Machines Corporation | 3 * Copyright (c) 2002-2014, International Business Machines Corporation |
| 4 * and others. All Rights Reserved. | 4 * and others. All Rights Reserved. |
| 5 ********************************************************************** | 5 ********************************************************************** |
| 6 * Date Name Description | 6 * Date Name Description |
| 7 * 01/14/2002 aliu Creation. | 7 * 01/14/2002 aliu Creation. |
| 8 ********************************************************************** | 8 ********************************************************************** |
| 9 */ | 9 */ |
| 10 | 10 |
| 11 #include "unicode/utypes.h" | 11 #include "unicode/utypes.h" |
| 12 | 12 |
| 13 #if !UCONFIG_NO_TRANSLITERATION | 13 #if !UCONFIG_NO_TRANSLITERATION |
| 14 | 14 |
| 15 #include "tridpars.h" | 15 #include "tridpars.h" |
| 16 #include "hash.h" | 16 #include "hash.h" |
| 17 #include "mutex.h" | 17 #include "mutex.h" |
| 18 #include "transreg.h" |
| 19 #include "uassert.h" |
| 18 #include "ucln_in.h" | 20 #include "ucln_in.h" |
| 19 #include "unicode/parsepos.h" | 21 #include "unicode/parsepos.h" |
| 20 #include "unicode/translit.h" | 22 #include "unicode/translit.h" |
| 21 #include "unicode/uchar.h" | 23 #include "unicode/uchar.h" |
| 22 #include "unicode/uniset.h" | 24 #include "unicode/uniset.h" |
| 23 #include "unicode/unistr.h" | 25 #include "unicode/unistr.h" |
| 24 #include "unicode/utrans.h" | 26 #include "unicode/utrans.h" |
| 25 #include "util.h" | 27 #include "util.h" |
| 26 #include "uvector.h" | 28 #include "uvector.h" |
| 27 | 29 |
| 28 U_NAMESPACE_BEGIN | 30 U_NAMESPACE_BEGIN |
| 29 | 31 |
| 30 static const UChar ID_DELIM = 0x003B; // ; | 32 static const UChar ID_DELIM = 0x003B; // ; |
| 31 static const UChar TARGET_SEP = 0x002D; // - | 33 static const UChar TARGET_SEP = 0x002D; // - |
| 32 static const UChar VARIANT_SEP = 0x002F; // / | 34 static const UChar VARIANT_SEP = 0x002F; // / |
| 33 static const UChar OPEN_REV = 0x0028; // ( | 35 static const UChar OPEN_REV = 0x0028; // ( |
| 34 static const UChar CLOSE_REV = 0x0029; // ) | 36 static const UChar CLOSE_REV = 0x0029; // ) |
| 35 | 37 |
| 36 //static const UChar EMPTY[] = {0}; // "" | 38 //static const UChar EMPTY[] = {0}; // "" |
| 37 static const UChar ANY[] = {65,110,121,0}; // "Any" | 39 static const UChar ANY[] = {65,110,121,0}; // "Any" |
| 38 static const UChar ANY_NULL[] = {65,110,121,45,78,117,108,108,0}; // "Any-Null" | 40 static const UChar ANY_NULL[] = {65,110,121,45,78,117,108,108,0}; // "Any-Null" |
| 39 | 41 |
| 40 static const int32_t FORWARD = UTRANS_FORWARD; | 42 static const int32_t FORWARD = UTRANS_FORWARD; |
| 41 static const int32_t REVERSE = UTRANS_REVERSE; | 43 static const int32_t REVERSE = UTRANS_REVERSE; |
| 42 | 44 |
| 43 static Hashtable* SPECIAL_INVERSES = NULL; | 45 static Hashtable* SPECIAL_INVERSES = NULL; |
| 46 static UInitOnce gSpecialInversesInitOnce = U_INITONCE_INITIALIZER; |
| 44 | 47 |
| 45 /** | 48 /** |
| 46 * The mutex controlling access to SPECIAL_INVERSES | 49 * The mutex controlling access to SPECIAL_INVERSES |
| 47 */ | 50 */ |
| 48 static UMutex LOCK = U_MUTEX_INITIALIZER; | 51 static UMutex LOCK = U_MUTEX_INITIALIZER; |
| 49 | 52 |
| 50 TransliteratorIDParser::Specs::Specs(const UnicodeString& s, const UnicodeString
& t, | 53 TransliteratorIDParser::Specs::Specs(const UnicodeString& s, const UnicodeString
& t, |
| 51 const UnicodeString& v, UBool sawS, | 54 const UnicodeString& v, UBool sawS, |
| 52 const UnicodeString& f) { | 55 const UnicodeString& f) { |
| 53 source = s; | 56 source = s; |
| (...skipping 583 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 637 * @param target the target against which to register the inverse | 640 * @param target the target against which to register the inverse |
| 638 * @param inverseTarget the inverse of target, that is | 641 * @param inverseTarget the inverse of target, that is |
| 639 * Any-target.getInverse() => Any-inverseTarget | 642 * Any-target.getInverse() => Any-inverseTarget |
| 640 * @param bidirectional if TRUE, register the reverse relation | 643 * @param bidirectional if TRUE, register the reverse relation |
| 641 * as well, that is, Any-inverseTarget.getInverse() => Any-target | 644 * as well, that is, Any-inverseTarget.getInverse() => Any-target |
| 642 */ | 645 */ |
| 643 void TransliteratorIDParser::registerSpecialInverse(const UnicodeString& target, | 646 void TransliteratorIDParser::registerSpecialInverse(const UnicodeString& target, |
| 644 const UnicodeString& inverse
Target, | 647 const UnicodeString& inverse
Target, |
| 645 UBool bidirectional, | 648 UBool bidirectional, |
| 646 UErrorCode &status) { | 649 UErrorCode &status) { |
| 647 init(status); | 650 umtx_initOnce(gSpecialInversesInitOnce, init, status); |
| 648 if (U_FAILURE(status)) { | 651 if (U_FAILURE(status)) { |
| 649 return; | 652 return; |
| 650 } | 653 } |
| 651 | 654 |
| 652 // If target == inverseTarget then force bidirectional => FALSE | 655 // If target == inverseTarget then force bidirectional => FALSE |
| 653 if (bidirectional && 0==target.caseCompare(inverseTarget, U_FOLD_CASE_DEFAUL
T)) { | 656 if (bidirectional && 0==target.caseCompare(inverseTarget, U_FOLD_CASE_DEFAUL
T)) { |
| 654 bidirectional = FALSE; | 657 bidirectional = FALSE; |
| 655 } | 658 } |
| 656 | 659 |
| 657 Mutex lock(&LOCK); | 660 Mutex lock(&LOCK); |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 844 * special inverse of that ID. If there is no special inverse | 847 * special inverse of that ID. If there is no special inverse |
| 845 * then return NULL. | 848 * then return NULL. |
| 846 * @return a SingleID or NULL. Returned object always has | 849 * @return a SingleID or NULL. Returned object always has |
| 847 * 'filter' field of NULL. | 850 * 'filter' field of NULL. |
| 848 */ | 851 */ |
| 849 TransliteratorIDParser::SingleID* | 852 TransliteratorIDParser::SingleID* |
| 850 TransliteratorIDParser::specsToSpecialInverse(const Specs& specs, UErrorCode &st
atus) { | 853 TransliteratorIDParser::specsToSpecialInverse(const Specs& specs, UErrorCode &st
atus) { |
| 851 if (0!=specs.source.caseCompare(ANY, 3, U_FOLD_CASE_DEFAULT)) { | 854 if (0!=specs.source.caseCompare(ANY, 3, U_FOLD_CASE_DEFAULT)) { |
| 852 return NULL; | 855 return NULL; |
| 853 } | 856 } |
| 854 init(status); | 857 umtx_initOnce(gSpecialInversesInitOnce, init, status); |
| 858 if (U_FAILURE(status)) { |
| 859 return NULL; |
| 860 } |
| 855 | 861 |
| 856 UnicodeString* inverseTarget; | 862 UnicodeString* inverseTarget; |
| 857 | 863 |
| 858 umtx_lock(&LOCK); | 864 umtx_lock(&LOCK); |
| 859 inverseTarget = (UnicodeString*) SPECIAL_INVERSES->get(specs.target); | 865 inverseTarget = (UnicodeString*) SPECIAL_INVERSES->get(specs.target); |
| 860 umtx_unlock(&LOCK); | 866 umtx_unlock(&LOCK); |
| 861 | 867 |
| 862 if (inverseTarget != NULL) { | 868 if (inverseTarget != NULL) { |
| 863 // If the original ID contained "Any-" then make the | 869 // If the original ID contained "Any-" then make the |
| 864 // special inverse "Any-Foo"; otherwise make it "Foo". | 870 // special inverse "Any-Foo"; otherwise make it "Foo". |
| (...skipping 22 matching lines...) Expand all Loading... |
| 887 /** | 893 /** |
| 888 * Glue method to get around access problems in C++. This would | 894 * Glue method to get around access problems in C++. This would |
| 889 * ideally be inline but we want to avoid a circular header | 895 * ideally be inline but we want to avoid a circular header |
| 890 * dependency. | 896 * dependency. |
| 891 */ | 897 */ |
| 892 Transliterator* TransliteratorIDParser::createBasicInstance(const UnicodeString&
id, const UnicodeString* canonID) { | 898 Transliterator* TransliteratorIDParser::createBasicInstance(const UnicodeString&
id, const UnicodeString* canonID) { |
| 893 return Transliterator::createBasicInstance(id, canonID); | 899 return Transliterator::createBasicInstance(id, canonID); |
| 894 } | 900 } |
| 895 | 901 |
| 896 /** | 902 /** |
| 897 * Initialize static memory. | 903 * Initialize static memory. Called through umtx_initOnce only. |
| 898 */ | 904 */ |
| 899 void TransliteratorIDParser::init(UErrorCode &status) { | 905 void TransliteratorIDParser::init(UErrorCode &status) { |
| 900 if (SPECIAL_INVERSES != NULL) { | 906 U_ASSERT(SPECIAL_INVERSES == NULL); |
| 901 return; | 907 ucln_i18n_registerCleanup(UCLN_I18N_TRANSLITERATOR, utrans_transliterator_cl
eanup); |
| 902 } | |
| 903 | 908 |
| 904 Hashtable* special_inverses = new Hashtable(TRUE, status); | 909 SPECIAL_INVERSES = new Hashtable(TRUE, status); |
| 905 // Null pointer check | 910 if (SPECIAL_INVERSES == NULL) { |
| 906 if (special_inverses == NULL) { | |
| 907 status = U_MEMORY_ALLOCATION_ERROR; | 911 status = U_MEMORY_ALLOCATION_ERROR; |
| 908 return; | 912 return; |
| 909 } | 913 } |
| 910 special_inverses->setValueDeleter(uprv_deleteUObject); | 914 SPECIAL_INVERSES->setValueDeleter(uprv_deleteUObject); |
| 911 | |
| 912 umtx_lock(&LOCK); | |
| 913 if (SPECIAL_INVERSES == NULL) { | |
| 914 SPECIAL_INVERSES = special_inverses; | |
| 915 special_inverses = NULL; | |
| 916 } | |
| 917 umtx_unlock(&LOCK); | |
| 918 delete special_inverses; /*null instance*/ | |
| 919 | |
| 920 ucln_i18n_registerCleanup(UCLN_I18N_TRANSLITERATOR, utrans_transliterator_cl
eanup); | |
| 921 } | 915 } |
| 922 | 916 |
| 923 /** | 917 /** |
| 924 * Free static memory. | 918 * Free static memory. |
| 925 */ | 919 */ |
| 926 void TransliteratorIDParser::cleanup() { | 920 void TransliteratorIDParser::cleanup() { |
| 927 if (SPECIAL_INVERSES) { | 921 if (SPECIAL_INVERSES) { |
| 928 delete SPECIAL_INVERSES; | 922 delete SPECIAL_INVERSES; |
| 929 SPECIAL_INVERSES = NULL; | 923 SPECIAL_INVERSES = NULL; |
| 930 } | 924 } |
| 925 gSpecialInversesInitOnce.reset(); |
| 931 } | 926 } |
| 932 | 927 |
| 933 U_NAMESPACE_END | 928 U_NAMESPACE_END |
| 934 | 929 |
| 935 #endif /* #if !UCONFIG_NO_TRANSLITERATION */ | 930 #endif /* #if !UCONFIG_NO_TRANSLITERATION */ |
| 936 | 931 |
| 937 //eof | 932 //eof |
| OLD | NEW |