[Libreoffice-commits] core.git: 10 commits - i18nlangtag/qa i18nlangtag/source include/i18nlangtag

Eike Rathke erack at redhat.com
Fri Sep 20 09:31:28 PDT 2013


 i18nlangtag/qa/cppunit/test_languagetag.cxx    |   22 +-
 i18nlangtag/source/isolang/mslangid.cxx        |    6 
 i18nlangtag/source/languagetag/languagetag.cxx |  242 +++++++++++++++++++++----
 include/i18nlangtag/languagetag.hxx            |    3 
 include/i18nlangtag/mslangid.hxx               |    1 
 5 files changed, 228 insertions(+), 46 deletions(-)

New commits:
commit f77085ce584b1400d4d245582fa3e214143e9c09
Author: Eike Rathke <erack at redhat.com>
Date:   Fri Sep 20 18:05:46 2013 +0200

    theDontKnow Impl
    
    Change-Id: I6d4738041e3f4eaffc3adbdb0b324eda24903b72

diff --git a/i18nlangtag/source/languagetag/languagetag.cxx b/i18nlangtag/source/languagetag/languagetag.cxx
index 3d2fc8a..01cd6d2 100644
--- a/i18nlangtag/source/languagetag/languagetag.cxx
+++ b/i18nlangtag/source/languagetag/languagetag.cxx
@@ -94,6 +94,7 @@ typedef ::std::map< OUString, LanguageTag::ImplPtr, compareIgnoreAsciiCaseLess >
 typedef ::std::map< LanguageType, LanguageTag::ImplPtr > MapLangID;
 struct theMapBcp47 : public rtl::Static< MapBcp47, theMapBcp47 > {};
 struct theMapLangID : public rtl::Static< MapLangID, theMapLangID > {};
+struct theDontKnow : public rtl::Static< LanguageTag::ImplPtr, theDontKnow > {};
 }
 
 
@@ -787,6 +788,16 @@ LanguageTag::ImplPtr LanguageTag::registerImpl() const
             }
         }
     }
+    else if (mbInitializedLangID && mnLangID == LANGUAGE_DONTKNOW)
+    {
+        // Heavy usage of LANGUAGE_DONTKNOW, make it an own Impl for all the
+        // conversion attempts. At the same time provide a central breakpoint
+        // to inspect such places.
+        LanguageTag::ImplPtr& rDontKnow = theDontKnow::get();
+        if (!rDontKnow)
+            rDontKnow.reset( new LanguageTagImpl( *this));
+        pImpl = rDontKnow;
+    }
     else
     {
         SAL_WARN( "i18nlangtag", "LanguageTag::registerImpl: can't register for 0x" << ::std::hex << mnLangID );
commit ababc9bba77784754b7c903d24f08b1869c584ef
Author: Eike Rathke <erack at redhat.com>
Date:   Fri Sep 20 17:32:27 2013 +0200

    0x
    
    Change-Id: Ie400046c513b278115ec6fc67b3c531a1153ef9e

diff --git a/i18nlangtag/source/languagetag/languagetag.cxx b/i18nlangtag/source/languagetag/languagetag.cxx
index bf835195..3d2fc8a 100644
--- a/i18nlangtag/source/languagetag/languagetag.cxx
+++ b/i18nlangtag/source/languagetag/languagetag.cxx
@@ -789,7 +789,7 @@ LanguageTag::ImplPtr LanguageTag::registerImpl() const
     }
     else
     {
-        SAL_WARN( "i18nlangtag", "LanguageTag::registerImpl: can't register for " << ::std::hex << mnLangID );
+        SAL_WARN( "i18nlangtag", "LanguageTag::registerImpl: can't register for 0x" << ::std::hex << mnLangID );
         pImpl.reset( new LanguageTagImpl( *this));
     }
     return pImpl;
commit 79dbf611175e8a91557e288feb463f78fa1a06b9
Author: Eike Rathke <erack at redhat.com>
Date:   Fri Sep 20 17:27:20 2013 +0200

    do not register LANGUAGE_DONTKNOW
    
    Change-Id: Ibfe4407c1b2740e806c7d9cb75529a8babc3fd92

diff --git a/i18nlangtag/source/languagetag/languagetag.cxx b/i18nlangtag/source/languagetag/languagetag.cxx
index 91de5fd..bf835195 100644
--- a/i18nlangtag/source/languagetag/languagetag.cxx
+++ b/i18nlangtag/source/languagetag/languagetag.cxx
@@ -676,7 +676,8 @@ LanguageTag::ImplPtr LanguageTag::registerImpl() const
 #endif
 
     // Prefer LangID map as find+insert needs less comparison work.
-    if (mbInitializedLangID)
+    // Never insert LANGUAGE_DONTKNOW
+    if (mbInitializedLangID && mnLangID != LANGUAGE_DONTKNOW)
     {
         MapLangID& rMap = theMapLangID::get();
         MapLangID::const_iterator it( rMap.find( mnLangID));
@@ -753,10 +754,13 @@ LanguageTag::ImplPtr LanguageTag::registerImpl() const
             OUString aBcp47;
             if (!bInsert)
             {
-                // May have involved canonicalize(), so compare with pImpl->maBcp47!
-                aBcp47 = LanguageTagImpl::convertToBcp47(
+                if (pImpl->mnLangID != LANGUAGE_DONTKNOW)
+                {
+                    // May have involved canonicalize(), so compare with pImpl->maBcp47!
+                    aBcp47 = LanguageTagImpl::convertToBcp47(
                             MsLangId::Conversion::convertLanguageToLocale( pImpl->mnLangID, true));
-                bInsert = (aBcp47 == pImpl->maBcp47);
+                    bInsert = (aBcp47 == pImpl->maBcp47);
+                }
             }
             // If round-trip is identical cross-insert to Bcp47 map.
             if (bInsert)
commit c640f19ca3aa1d918bd8df454d5ec45fbc2fad05
Author: Eike Rathke <erack at redhat.com>
Date:   Fri Sep 20 16:41:59 2013 +0200

    now with on-the-fly LangID assignment
    
    Change-Id: I0766705191176381beaf331de3d10dfc0086a9b4

diff --git a/i18nlangtag/qa/cppunit/test_languagetag.cxx b/i18nlangtag/qa/cppunit/test_languagetag.cxx
index 945fc74..91ef1ef 100644
--- a/i18nlangtag/qa/cppunit/test_languagetag.cxx
+++ b/i18nlangtag/qa/cppunit/test_languagetag.cxx
@@ -74,7 +74,7 @@ void TestLanguageTag::testAllTags()
         CPPUNIT_ASSERT( aLocale.Language == "qlt" );
         CPPUNIT_ASSERT( aLocale.Country == "DE" );
         CPPUNIT_ASSERT( aLocale.Variant == "de-Latn-DE" );
-        CPPUNIT_ASSERT( nLanguageType == LANGUAGE_SYSTEM );     // XXX not resolved!
+        CPPUNIT_ASSERT( LanguageTag::isOnTheFlyID( nLanguageType) );    // XXX not canonicalized!
         CPPUNIT_ASSERT( de_DE.getLanguage() == "de" );
         CPPUNIT_ASSERT( de_DE.getCountry() == "DE" );
         CPPUNIT_ASSERT( de_DE.getScript() == "Latn" );
@@ -92,19 +92,25 @@ void TestLanguageTag::testAllTags()
         CPPUNIT_ASSERT( aLocale.Language == "tlh" );
         CPPUNIT_ASSERT( aLocale.Country == "" );
         CPPUNIT_ASSERT( aLocale.Variant == "" );
-        CPPUNIT_ASSERT( klingon.getLanguageType() == LANGUAGE_SYSTEM );
+        CPPUNIT_ASSERT( LanguageTag::isOnTheFlyID( klingon.getLanguageType()) );
         CPPUNIT_ASSERT( klingon.isValidBcp47() == true );
         CPPUNIT_ASSERT( klingon.isIsoLocale() == true );
         CPPUNIT_ASSERT( klingon.isIsoODF() == true );
+        LanguageType nLang = klingon.getLanguageType();
+        LanguageTag klingon_id( nLang);
+        CPPUNIT_ASSERT( klingon_id.getBcp47() == "tlh" );
 #else
         CPPUNIT_ASSERT( klingon.getBcp47() == s_klingon );
         CPPUNIT_ASSERT( aLocale.Language == "qlt" );
         CPPUNIT_ASSERT( aLocale.Country == "" );
         CPPUNIT_ASSERT( aLocale.Variant == s_klingon );
-        CPPUNIT_ASSERT( klingon.getLanguageType() == LANGUAGE_SYSTEM );
+        CPPUNIT_ASSERT( LanguageTag::isOnTheFlyID( klingon.getLanguageType()) );
         CPPUNIT_ASSERT( klingon.isValidBcp47() == true );
         CPPUNIT_ASSERT( klingon.isIsoLocale() == false );
         CPPUNIT_ASSERT( klingon.isIsoODF() == false );
+        LanguageType nLang = klingon.getLanguageType();
+        LanguageTag klingon_id( nLang);
+        CPPUNIT_ASSERT( klingon_id.getBcp47() == s_klingon );
 #endif
     }
 
@@ -232,7 +238,7 @@ void TestLanguageTag::testAllTags()
         CPPUNIT_ASSERT( aLocale.Language == "qlt" );
         CPPUNIT_ASSERT( aLocale.Country == "" );
         CPPUNIT_ASSERT( aLocale.Variant == s_ca_valencia );
-        CPPUNIT_ASSERT( ca_valencia.getLanguageType() == LANGUAGE_SYSTEM );
+        CPPUNIT_ASSERT( LanguageTag::isOnTheFlyID( ca_valencia.getLanguageType()) );
         CPPUNIT_ASSERT( ca_valencia.isValidBcp47() == true );
         CPPUNIT_ASSERT( ca_valencia.isIsoLocale() == false );
         CPPUNIT_ASSERT( ca_valencia.isIsoODF() == false );
@@ -328,7 +334,7 @@ void TestLanguageTag::testAllTags()
         CPPUNIT_ASSERT( aLocale.Language == "qlt" );
         CPPUNIT_ASSERT( aLocale.Country == "" );
         CPPUNIT_ASSERT( aLocale.Variant == s_de_1901 );
-        CPPUNIT_ASSERT( de_1901.getLanguageType() == LANGUAGE_SYSTEM );
+        CPPUNIT_ASSERT( LanguageTag::isOnTheFlyID( de_1901.getLanguageType()) );
         CPPUNIT_ASSERT( de_1901.isValidBcp47() == true );
         CPPUNIT_ASSERT( de_1901.isIsoLocale() == false );
         CPPUNIT_ASSERT( de_1901.isIsoODF() == false );
@@ -385,7 +391,7 @@ void TestLanguageTag::testAllTags()
         CPPUNIT_ASSERT( aLocale.Language == "qty" );
         CPPUNIT_ASSERT( aLocale.Country == "" );
         CPPUNIT_ASSERT( aLocale.Variant == "" );
-        CPPUNIT_ASSERT( qty.getLanguageType() == LANGUAGE_SYSTEM );
+        CPPUNIT_ASSERT( LanguageTag::isOnTheFlyID( qty.getLanguageType()) );
     }
 
     // 'x-comment' is a privateuse known "locale"
@@ -409,7 +415,7 @@ void TestLanguageTag::testAllTags()
         CPPUNIT_ASSERT( aLocale.Language == "qlt" );
         CPPUNIT_ASSERT( aLocale.Country == "" );
         CPPUNIT_ASSERT( aLocale.Variant == "x-foobar" );
-        CPPUNIT_ASSERT( xfoobar.getLanguageType() == LANGUAGE_SYSTEM );
+        CPPUNIT_ASSERT( LanguageTag::isOnTheFlyID( xfoobar.getLanguageType()) );
     }
 
     // '*' the dreaded jolly joker is a "privateuse" known "locale"
@@ -470,7 +476,7 @@ void TestLanguageTag::testAllTags()
         CPPUNIT_ASSERT( aLocale.Language == "qlt" );
         CPPUNIT_ASSERT( aLocale.Country == "" );
         CPPUNIT_ASSERT( aLocale.Variant == s_uab );
-        CPPUNIT_ASSERT( uab.getLanguageType() == LANGUAGE_SYSTEM );
+        CPPUNIT_ASSERT( uab.getLanguageType() == LANGUAGE_DONTKNOW );
         CPPUNIT_ASSERT( uab.isValidBcp47() == false );
         CPPUNIT_ASSERT( uab.isIsoLocale() == false );
         CPPUNIT_ASSERT( uab.isIsoODF() == false );
diff --git a/i18nlangtag/source/isolang/mslangid.cxx b/i18nlangtag/source/isolang/mslangid.cxx
index 0b0253f..f547c34 100644
--- a/i18nlangtag/source/isolang/mslangid.cxx
+++ b/i18nlangtag/source/isolang/mslangid.cxx
@@ -177,11 +177,7 @@ LanguageType MsLangId::Conversion::convertLocaleToLanguage(
     if (rLocale.Language.isEmpty())
         return LANGUAGE_SYSTEM;
 
-    LanguageType nRet = convertLocaleToLanguageImpl( rLocale);
-    if (nRet == LANGUAGE_DONTKNOW)
-        nRet = LANGUAGE_SYSTEM;
-
-    return nRet;
+    return convertLocaleToLanguageImpl( rLocale);
 }
 
 
diff --git a/i18nlangtag/source/languagetag/languagetag.cxx b/i18nlangtag/source/languagetag/languagetag.cxx
index e960ea9..91de5fd 100644
--- a/i18nlangtag/source/languagetag/languagetag.cxx
+++ b/i18nlangtag/source/languagetag/languagetag.cxx
@@ -740,7 +740,9 @@ LanguageTag::ImplPtr LanguageTag::registerImpl() const
             if (pImpl->synCanonicalize())
             {
                 SAL_INFO( "i18nlangtag", "LanguageTag::registerImpl: canonicalized to '" << pImpl->maBcp47 << "'");
-                rMap.insert( ::std::make_pair( pImpl->maBcp47, pImpl));
+                bool bInserted = rMap.insert( ::std::make_pair( pImpl->maBcp47, pImpl)).second;
+                SAL_INFO( "i18nlangtag", "LanguageTag::registerImpl: " << (bInserted ? "" : "not ") << "inserted '"
+                        << pImpl->maBcp47 << "'");
             }
             // Try round-trip Bcp47->Locale->LangID->Locale->Bcp47.
             if (!pImpl->mbInitializedLocale)
@@ -1122,7 +1124,16 @@ void LanguageTagImpl::convertLocaleToLang( bool bAllowOnTheFlyID )
     else
     {
         mnLangID = MsLangId::Conversion::convertLocaleToLanguage( maLocale);
-        (void)bAllowOnTheFlyID;
+        if (mnLangID == LANGUAGE_DONTKNOW && bAllowOnTheFlyID)
+        {
+            if (isValidBcp47())
+                registerOnTheFly();
+            else
+            {
+                SAL_WARN( "i18nlangtag", "LanguageTagImpl::convertLocaleToLang: with bAllowOnTheFlyID invalid '"
+                        << maBcp47 << "'");
+            }
+        }
     }
     mbInitializedLangID = true;
 }
commit 75cb1e8541f1fb377fd4504ef5fd6ffea6bee7a1
Author: Eike Rathke <erack at redhat.com>
Date:   Fri Sep 20 15:45:50 2013 +0200

    more preparation for on-the-fli IDs
    
    Change-Id: Ic4d53d0e3e8e149d09017dd7a567b879601073fc

diff --git a/i18nlangtag/source/languagetag/languagetag.cxx b/i18nlangtag/source/languagetag/languagetag.cxx
index ee4a142..e960ea9 100644
--- a/i18nlangtag/source/languagetag/languagetag.cxx
+++ b/i18nlangtag/source/languagetag/languagetag.cxx
@@ -277,7 +277,7 @@ private:
     bool                isValidBcp47() const;
 
     void                convertLocaleToBcp47();
-    void                convertLocaleToLang();
+    void                convertLocaleToLang( bool bAllowOnTheFlyID );
     void                convertBcp47ToLocale();
     void                convertBcp47ToLang();
     void                convertLangToLocale();
@@ -736,17 +736,28 @@ LanguageTag::ImplPtr LanguageTag::registerImpl() const
             SAL_INFO( "i18nlangtag", "LanguageTag::registerImpl: new impl for '" << maBcp47 << "'");
             pImpl.reset( new LanguageTagImpl( *this));
             rMap.insert( ::std::make_pair( maBcp47, pImpl));
+            // If changed after canonicalize() also add the resulting tag to map.
+            if (pImpl->synCanonicalize())
+            {
+                SAL_INFO( "i18nlangtag", "LanguageTag::registerImpl: canonicalized to '" << pImpl->maBcp47 << "'");
+                rMap.insert( ::std::make_pair( pImpl->maBcp47, pImpl));
+            }
             // Try round-trip Bcp47->Locale->LangID->Locale->Bcp47.
             if (!pImpl->mbInitializedLocale)
                 pImpl->convertBcp47ToLocale();
             if (!pImpl->mbInitializedLangID)
-                pImpl->convertLocaleToLang();
-            OUString aBcp47( LanguageTagImpl::convertToBcp47(
-                        MsLangId::Conversion::convertLanguageToLocale( pImpl->mnLangID, true)));
+                pImpl->convertLocaleToLang( true);
+            bool bInsert = LanguageTag::isOnTheFlyID( pImpl->mnLangID);
+            OUString aBcp47;
+            if (!bInsert)
+            {
+                // May have involved canonicalize(), so compare with pImpl->maBcp47!
+                aBcp47 = LanguageTagImpl::convertToBcp47(
+                            MsLangId::Conversion::convertLanguageToLocale( pImpl->mnLangID, true));
+                bInsert = (aBcp47 == pImpl->maBcp47);
+            }
             // If round-trip is identical cross-insert to Bcp47 map.
-            // May have involved canonicalize(), so compare with
-            // pImpl->maBcp47!
-            if (aBcp47 == pImpl->maBcp47)
+            if (bInsert)
             {
                 ::std::pair< MapLangID::const_iterator, bool > res(
                         theMapLangID::get().insert( ::std::make_pair( pImpl->mnLangID, pImpl)));
@@ -940,7 +951,7 @@ bool LanguageTagImpl::canonicalize()
             {
                 if (!mbInitializedLangID)
                 {
-                    convertLocaleToLang();
+                    convertLocaleToLang( false);
                     if (bTemporaryLocale)
                         bTemporaryLangID = true;
                 }
@@ -1102,7 +1113,7 @@ void LanguageTag::convertLocaleToBcp47()
 }
 
 
-void LanguageTagImpl::convertLocaleToLang()
+void LanguageTagImpl::convertLocaleToLang( bool bAllowOnTheFlyID )
 {
     if (mbSystemLocale)
     {
@@ -1111,6 +1122,7 @@ void LanguageTagImpl::convertLocaleToLang()
     else
     {
         mnLangID = MsLangId::Conversion::convertLocaleToLanguage( maLocale);
+        (void)bAllowOnTheFlyID;
     }
     mbInitializedLangID = true;
 }
@@ -1118,7 +1130,7 @@ void LanguageTagImpl::convertLocaleToLang()
 
 void LanguageTag::convertLocaleToLang()
 {
-    getImpl()->convertLocaleToLang();
+    getImpl()->convertLocaleToLang( true);
     syncFromImpl();
 }
 
@@ -1159,7 +1171,7 @@ void LanguageTagImpl::convertBcp47ToLang()
     {
         if (!mbInitializedLocale)
             convertBcp47ToLocale();
-        convertLocaleToLang();
+        convertLocaleToLang( true);
     }
     mbInitializedLangID = true;
 }
commit 01bde208acc429a0c65fdf6e65415ebea72e9ddc
Author: Eike Rathke <erack at redhat.com>
Date:   Fri Sep 20 15:39:06 2013 +0200

    added isOnTheFlyID()
    
    Change-Id: Ifddbec485814e3287e671e6bc4059689ca3f6c93

diff --git a/i18nlangtag/source/languagetag/languagetag.cxx b/i18nlangtag/source/languagetag/languagetag.cxx
index 7d03597..ee4a142 100644
--- a/i18nlangtag/source/languagetag/languagetag.cxx
+++ b/i18nlangtag/source/languagetag/languagetag.cxx
@@ -126,6 +126,17 @@ static LanguageType getNextOnTheFlyLanguage()
 }
 
 
+// static
+bool LanguageTag::isOnTheFlyID( LanguageType nLang )
+{
+    LanguageType nPri = MsLangId::getPrimaryLanguage( nLang);
+    LanguageType nSub = MsLangId::getSubLanguage( nLang);
+    return
+        LANGUAGE_ON_THE_FLY_START <= nPri && nPri <= LANGUAGE_ON_THE_FLY_END &&
+        LANGUAGE_ON_THE_FLY_SUB_START <= nSub && nSub <= LANGUAGE_ON_THE_FLY_SUB_END;
+}
+
+
 /** A reference holder for liblangtag data de/initialization, one static
     instance. Currently implemented such that the first "ref" inits and dtor
     (our library deinitialized) tears down.
diff --git a/include/i18nlangtag/languagetag.hxx b/include/i18nlangtag/languagetag.hxx
index 50cfef5..27bcb34 100644
--- a/include/i18nlangtag/languagetag.hxx
+++ b/include/i18nlangtag/languagetag.hxx
@@ -484,6 +484,9 @@ public:
      */
     static com::sun::star::lang::Locale convertToLocaleWithFallback( const OUString& rBcp47 );
 
+    /** If nLang is a generated on-the-fly LangID */
+    static bool         isOnTheFlyID( LanguageType nLang );
+
     typedef ::boost::shared_ptr< LanguageTagImpl > ImplPtr;
 
 private:
commit e81359a9a3240187bf3a02fdb48b8709238bdc51
Author: Eike Rathke <erack at redhat.com>
Date:   Fri Sep 20 14:47:27 2013 +0200

    added registerImpl() re-entered warning
    
    Change-Id: I064d7241343fadd0256bb0fa5ad32fabcd6738a4

diff --git a/i18nlangtag/source/languagetag/languagetag.cxx b/i18nlangtag/source/languagetag/languagetag.cxx
index 98dd2a5..7d03597 100644
--- a/i18nlangtag/source/languagetag/languagetag.cxx
+++ b/i18nlangtag/source/languagetag/languagetag.cxx
@@ -654,6 +654,16 @@ LanguageTag::ImplPtr LanguageTag::registerImpl() const
 
     osl::MutexGuard aGuard( theMutex::get());
 
+#if OSL_DEBUG_LEVEL > 0
+    static long nRunning = 0;
+    // Entering twice here is ok, which is needed for fallback init in
+    // getKnowns() in canonicalize() via pImpl->convertBcp47ToLocale() below,
+    // everything else is suspicious.
+    SAL_WARN_IF( nRunning > 1, "i18nlangtag", "LanguageTag::registerImpl: re-entered for '"
+            << maBcp47 << "' 0x" << ::std::hex << mnLangID );
+    struct Runner { Runner() { ++nRunning; } ~Runner() { --nRunning; } } aRunner;
+#endif
+
     // Prefer LangID map as find+insert needs less comparison work.
     if (mbInitializedLangID)
     {
commit 5ec8a9b13a5805d641555fa35057965f6f45a420
Author: Eike Rathke <erack at redhat.com>
Date:   Fri Sep 20 14:07:47 2013 +0200

    added registerOnTheFly()
    
    Change-Id: I1e270686ad73bf32c580dddcab7f03c4a3d85054

diff --git a/i18nlangtag/source/languagetag/languagetag.cxx b/i18nlangtag/source/languagetag/languagetag.cxx
index f1f05d8..98dd2a5 100644
--- a/i18nlangtag/source/languagetag/languagetag.cxx
+++ b/i18nlangtag/source/languagetag/languagetag.cxx
@@ -97,9 +97,6 @@ struct theMapLangID : public rtl::Static< MapLangID, theMapLangID > {};
 }
 
 
-/* TODO: this is how on-the-fly LangID assignment will work, now implement
- * usage and registration. */
-#if 0
 static LanguageType getNextOnTheFlyLanguage()
 {
     static LanguageType nOnTheFlyLanguage = 0;
@@ -116,15 +113,17 @@ static LanguageType getNextOnTheFlyLanguage()
             if (nSub != LANGUAGE_ON_THE_FLY_SUB_END)
                 nOnTheFlyLanguage = MsLangId::makeLangID( ++nSub, LANGUAGE_ON_THE_FLY_START);
             else
+            {
                 SAL_WARN( "i18nlangtag", "getNextOnTheFlyLanguage: none left! ("
                         << ((LANGUAGE_ON_THE_FLY_END - LANGUAGE_ON_THE_FLY_START + 1)
                             * (LANGUAGE_ON_THE_FLY_SUB_END - LANGUAGE_ON_THE_FLY_SUB_START + 1))
                         << " consumed?!?)");
+                return 0;
+            }
         }
     }
     return nOnTheFlyLanguage;
 }
-#endif
 
 
 /** A reference holder for liblangtag data de/initialization, one static
@@ -289,6 +288,12 @@ private:
     OUString            getRegionFromLangtag();
     OUString            getVariantsFromLangtag();
 
+    /** Generates on-the-fly LangID and registers the maBcp47,mnLangID pair.
+
+        @return NULL if no ID could be obtained or registration failed.
+     */
+    LanguageTag::ImplPtr registerOnTheFly();
+
     /** Obtain Language, Script, Country and Variants via simpleExtract() and
         assign them to the cached variables if successful.
 
@@ -325,7 +330,7 @@ private:
 
     /** Convert Locale to BCP 47 string without resolving system and creating
         temporary LanguageTag instances. */
-    static OUString convertToBcp47( const com::sun::star::lang::Locale& rLocale );
+    static OUString     convertToBcp47( const com::sun::star::lang::Locale& rLocale );
 
 };
 
@@ -557,6 +562,72 @@ LanguageTag::~LanguageTag()
 }
 
 
+LanguageTag::ImplPtr LanguageTagImpl::registerOnTheFly()
+{
+    LanguageTag::ImplPtr pImpl;
+
+    if (!mbInitializedBcp47)
+    {
+        if (mbInitializedLocale)
+        {
+            maBcp47 = LanguageTagImpl::convertToBcp47( maLocale);
+            mbInitializedBcp47 = !maBcp47.isEmpty();
+        }
+    }
+    if (maBcp47.isEmpty())
+    {
+        SAL_WARN( "i18nlangtag", "LanguageTagImpl::registerOnTheFly: no Bcp47 string, no registering");
+        return pImpl;
+    }
+
+    LanguageType nLang = getNextOnTheFlyLanguage();
+    if (!nLang)
+    {
+        // out of IDs, nothing to register
+        return pImpl;
+    }
+    mnLangID = nLang;
+    mbInitializedLangID = true;
+
+    osl::MutexGuard aGuard( theMutex::get());
+
+    MapBcp47& rMap = theMapBcp47::get();
+    MapBcp47::const_iterator it( rMap.find( maBcp47));
+    if (it != rMap.end())
+    {
+        SAL_INFO( "i18nlangtag", "LanguageTag::registerOnTheFly: found impl for '" << maBcp47 << "'");
+        pImpl = (*it).second;
+        if (pImpl.get() != this)
+        {
+            SAL_WARN( "i18nlangtag", "LanguageTag::registerOnTheFly: impl should be this");
+            *pImpl = *this;     // ensure consistency
+        }
+    }
+    else
+    {
+        SAL_INFO( "i18nlangtag", "LanguageTag::registerOnTheFly: new impl for '" << maBcp47 << "'");
+        pImpl.reset( new LanguageTagImpl( *this));
+        rMap.insert( ::std::make_pair( maBcp47, pImpl));
+    }
+
+    ::std::pair< MapLangID::const_iterator, bool > res(
+            theMapLangID::get().insert( ::std::make_pair( pImpl->mnLangID, pImpl)));
+    if (res.second)
+    {
+        SAL_INFO( "i18nlangtag", "LanguageTag::registerOnTheFly: cross-inserted 0x"
+                << ::std::hex << pImpl->mnLangID << " for '" << maBcp47 << "'");
+    }
+    else
+    {
+        SAL_WARN( "i18nlangtag", "LanguageTag::registerOnTheFly: not cross-inserted 0x"
+                << ::std::hex << pImpl->mnLangID << " for '" << maBcp47 << "' have '"
+                << (*res.first).second->maBcp47 << "'");
+    }
+
+    return pImpl;
+}
+
+
 LanguageTag::ImplPtr LanguageTag::registerImpl() const
 {
     // XXX NOTE: Do not use non-static LanguageTag::convert...() member methods
commit e3a01c2b0c00a502622f3b6f0be560cf32b3b774
Author: Eike Rathke <erack at redhat.com>
Date:   Fri Sep 20 13:36:33 2013 +0200

    check for identity in operator=()
    
    Change-Id: I687dc4bdd3093054a6e2c1fd383cfc2a8c948303

diff --git a/i18nlangtag/source/languagetag/languagetag.cxx b/i18nlangtag/source/languagetag/languagetag.cxx
index 3154639..f1f05d8 100644
--- a/i18nlangtag/source/languagetag/languagetag.cxx
+++ b/i18nlangtag/source/languagetag/languagetag.cxx
@@ -383,6 +383,9 @@ LanguageTagImpl::LanguageTagImpl( const LanguageTagImpl & rLanguageTagImpl )
 
 LanguageTagImpl& LanguageTagImpl::operator=( const LanguageTagImpl & rLanguageTagImpl )
 {
+    if (&rLanguageTagImpl == this)
+        return *this;
+
     maLocale            = rLanguageTagImpl.maLocale;
     maBcp47             = rLanguageTagImpl.maBcp47;
     maCachedLanguage    = rLanguageTagImpl.maCachedLanguage;
@@ -534,6 +537,9 @@ LanguageTag::LanguageTag( const LanguageTag & rLanguageTag )
 
 LanguageTag& LanguageTag::operator=( const LanguageTag & rLanguageTag )
 {
+    if (&rLanguageTag == this)
+        return *this;
+
     maLocale            = rLanguageTag.maLocale;
     maBcp47             = rLanguageTag.maBcp47;
     mnLangID            = rLanguageTag.mnLangID;
commit 862766d569e51d91c11139cc831fb083c8bbdd01
Author: Eike Rathke <erack at redhat.com>
Date:   Fri Sep 20 12:11:13 2013 +0200

    prepare for on-the-fly assigned LangIDs
    
    Change-Id: Id4ba99f0b1894457ca95c209b8394447c6fd7893

diff --git a/i18nlangtag/source/languagetag/languagetag.cxx b/i18nlangtag/source/languagetag/languagetag.cxx
index 11cec0c..3154639 100644
--- a/i18nlangtag/source/languagetag/languagetag.cxx
+++ b/i18nlangtag/source/languagetag/languagetag.cxx
@@ -323,6 +323,10 @@ private:
                                        OUString& rCountry,
                                        OUString& rVariants );
 
+    /** Convert Locale to BCP 47 string without resolving system and creating
+        temporary LanguageTag instances. */
+    static OUString convertToBcp47( const com::sun::star::lang::Locale& rLocale );
+
 };
 
 
@@ -551,7 +555,9 @@ LanguageTag::ImplPtr LanguageTag::registerImpl() const
 {
     // XXX NOTE: Do not use non-static LanguageTag::convert...() member methods
     // here as they access getImpl() and syncFromImpl() and would lead to
-    // recursion.
+    // recursion. Also do not use the static LanguageTag::convertTo...()
+    // methods as they may create temporary LanguageTag instances. Only
+    // LanguageTagImpl::convertToBcp47(Locale) is ok.
 
     ImplPtr pImpl;
 
@@ -565,8 +571,8 @@ LanguageTag::ImplPtr LanguageTag::registerImpl() const
     // Force Bcp47 if not LangID.
     if (!mbInitializedLangID && !mbInitializedBcp47 && mbInitializedLocale)
     {
-        maBcp47 = LanguageTag::convertToBcp47( maLocale, true);
-        mbInitializedBcp47 = true;
+        maBcp47 = LanguageTagImpl::convertToBcp47( maLocale);
+        mbInitializedBcp47 = !maBcp47.isEmpty();
     }
 
     osl::MutexGuard aGuard( theMutex::get());
@@ -637,7 +643,7 @@ LanguageTag::ImplPtr LanguageTag::registerImpl() const
                 pImpl->convertBcp47ToLocale();
             if (!pImpl->mbInitializedLangID)
                 pImpl->convertLocaleToLang();
-            OUString aBcp47( LanguageTag::convertToBcp47(
+            OUString aBcp47( LanguageTagImpl::convertToBcp47(
                         MsLangId::Conversion::convertLanguageToLocale( pImpl->mnLangID, true)));
             // If round-trip is identical cross-insert to Bcp47 map.
             // May have involved canonicalize(), so compare with
@@ -966,7 +972,19 @@ void LanguageTagImpl::convertLocaleToBcp47()
     if (mbSystemLocale && !mbInitializedLocale)
         convertLangToLocale();
 
-    if (maLocale.Language == I18NLANGTAG_QLT)
+    if (maLocale.Language.isEmpty())
+    {
+        // Do not call LanguageTag::convertToBcp47(Locale) that for an empty
+        // locale via LanguageTag::convertToBcp47(LanguageType) and
+        // LanguageTag::convertToLocale(LanguageType) would instanciate another
+        // LanguageTag.
+        maLocale = MsLangId::Conversion::convertLanguageToLocale( LANGUAGE_SYSTEM, true);
+    }
+    if (maLocale.Language.isEmpty())
+    {
+        maBcp47 = OUString();   // bad luck
+    }
+    else if (maLocale.Language == I18NLANGTAG_QLT)
     {
         maBcp47 = maLocale.Variant;
         meIsIsoLocale = DECISION_NO;
@@ -994,7 +1012,7 @@ void LanguageTagImpl::convertLocaleToLang()
     }
     else
     {
-        mnLangID = LanguageTag::convertToLanguageType( maLocale, true);
+        mnLangID = MsLangId::Conversion::convertLocaleToLanguage( maLocale);
     }
     mbInitializedLangID = true;
 }
@@ -1064,7 +1082,7 @@ void LanguageTagImpl::convertLangToLocale()
         mbInitializedLangID = true;
     }
     // Resolve system here! The original is remembered as mbSystemLocale.
-    maLocale = LanguageTag::convertToLocale( mnLangID, true);
+    maLocale = MsLangId::Conversion::convertLanguageToLocale( mnLangID, true);
     mbInitializedLocale = true;
 }
 
@@ -2126,7 +2144,7 @@ com::sun::star::lang::Locale LanguageTag::convertToLocale( LanguageType nLangID,
     if (!bResolveSystem && lcl_isSystem( nLangID))
         return lang::Locale();
 
-    return MsLangId::Conversion::convertLanguageToLocale( nLangID, bResolveSystem);
+    return LanguageTag( nLangID).getLocale( bResolveSystem);
 }
 
 
@@ -2136,19 +2154,17 @@ LanguageType LanguageTag::convertToLanguageType( const com::sun::star::lang::Loc
     if (rLocale.Language.isEmpty() && !bResolveSystem)
         return LANGUAGE_SYSTEM;
 
-    return MsLangId::Conversion::convertLocaleToLanguage( rLocale);
+    return LanguageTag( rLocale).getLanguageType( bResolveSystem);
 }
 
 
 // static
-OUString LanguageTag::convertToBcp47( const com::sun::star::lang::Locale& rLocale, bool bResolveSystem )
+OUString LanguageTagImpl::convertToBcp47( const com::sun::star::lang::Locale& rLocale )
 {
     OUString aBcp47;
     if (rLocale.Language.isEmpty())
     {
-        if (bResolveSystem)
-            aBcp47 = convertToBcp47( LANGUAGE_SYSTEM, true);
-        // else aBcp47 stays empty
+        // aBcp47 stays empty
     }
     else if (rLocale.Language == I18NLANGTAG_QLT)
     {
@@ -2171,25 +2187,46 @@ OUString LanguageTag::convertToBcp47( const com::sun::star::lang::Locale& rLocal
 
 
 // static
+OUString LanguageTag::convertToBcp47( const com::sun::star::lang::Locale& rLocale, bool bResolveSystem )
+{
+    OUString aBcp47;
+    if (rLocale.Language.isEmpty())
+    {
+        if (bResolveSystem)
+            aBcp47 = LanguageTag::convertToBcp47( LANGUAGE_SYSTEM, true);
+        // else aBcp47 stays empty
+    }
+    else
+    {
+        aBcp47 = LanguageTagImpl::convertToBcp47( rLocale);
+    }
+    return aBcp47;
+}
+
+
+// static
 OUString LanguageTag::convertToBcp47( LanguageType nLangID, bool bResolveSystem )
 {
     // Catch this first so we don't need the rest.
     if (!bResolveSystem && lcl_isSystem( nLangID))
         return OUString();
 
-    lang::Locale aLocale( convertToLocale( nLangID, bResolveSystem));
+    lang::Locale aLocale( LanguageTag::convertToLocale( nLangID, bResolveSystem));
     // If system for some reason (should not happen.. haha) could not be
-    // resolved DO NOT CALL convertToBcp47() because that would recurse into
-    // this method here!
+    // resolved DO NOT CALL LanguageTag::convertToBcp47(Locale) because that
+    // would recurse into this method here!
     if (aLocale.Language.isEmpty() && bResolveSystem)
         return OUString();      // bad luck, bail out
-    return convertToBcp47( aLocale, bResolveSystem);
+    return LanguageTagImpl::convertToBcp47( aLocale);
 }
 
 
 // static
 com::sun::star::lang::Locale LanguageTag::convertToLocale( const OUString& rBcp47, bool bResolveSystem )
 {
+    if (rBcp47.isEmpty() && !bResolveSystem)
+        return lang::Locale();
+
     return LanguageTag( rBcp47).getLocale( bResolveSystem);
 }
 
@@ -2197,6 +2234,9 @@ com::sun::star::lang::Locale LanguageTag::convertToLocale( const OUString& rBcp4
 // static
 LanguageType LanguageTag::convertToLanguageType( const OUString& rBcp47, bool bResolveSystem )
 {
+    if (rBcp47.isEmpty() && !bResolveSystem)
+        return LANGUAGE_SYSTEM;
+
     return LanguageTag( rBcp47).getLanguageType( bResolveSystem);
 }
 
diff --git a/include/i18nlangtag/mslangid.hxx b/include/i18nlangtag/mslangid.hxx
index 95adb91..e0582d8 100644
--- a/include/i18nlangtag/mslangid.hxx
+++ b/include/i18nlangtag/mslangid.hxx
@@ -200,6 +200,7 @@ public:
     private:
 
         friend class LanguageTag;
+        friend class LanguageTagImpl;
 
         friend ::com::sun::star::lang::Locale MsLangId::getFallbackLocale(
                 const ::com::sun::star::lang::Locale & rLocale );


More information about the Libreoffice-commits mailing list