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

Eike Rathke erack at redhat.com
Thu Aug 29 08:33:04 PDT 2013


 i18nlangtag/qa/cppunit/test_languagetag.cxx       |   11 -
 i18nlangtag/source/languagetag/simple-langtag.cxx |  129 +++++++++++++++++-----
 2 files changed, 104 insertions(+), 36 deletions(-)

New commits:
commit 9b98e25ce1e76a86ecf1dce71349e13ce1c1e6d5
Author: Eike Rathke <erack at redhat.com>
Date:   Thu Aug 29 17:31:52 2013 +0200

    handle variants in replacement code
    
    Change-Id: I57da3bcd415c060b1e785e0d1cf3966de819c196

diff --git a/i18nlangtag/qa/cppunit/test_languagetag.cxx b/i18nlangtag/qa/cppunit/test_languagetag.cxx
index fd55e0b..915d5cb 100644
--- a/i18nlangtag/qa/cppunit/test_languagetag.cxx
+++ b/i18nlangtag/qa/cppunit/test_languagetag.cxx
@@ -167,19 +167,11 @@ void TestLanguageTag::testAllTags()
         CPPUNIT_ASSERT( ca_ES_valencia.getScript() == "" );
         CPPUNIT_ASSERT( ca_ES_valencia.getLanguageAndScript() == "ca" );
         ::std::vector< OUString > ca_ES_valencia_Fallbacks( ca_ES_valencia.getFallbackStrings());
-        /* TODO: replacement doesn't handle variants yet. */
-#if USE_LIBLANGTAG
         CPPUNIT_ASSERT( ca_ES_valencia_Fallbacks.size() == 4);
         CPPUNIT_ASSERT( ca_ES_valencia_Fallbacks[0] == "ca-ES-valencia");
         CPPUNIT_ASSERT( ca_ES_valencia_Fallbacks[1] == "ca-valencia");
         CPPUNIT_ASSERT( ca_ES_valencia_Fallbacks[2] == "ca-ES");
         CPPUNIT_ASSERT( ca_ES_valencia_Fallbacks[3] == "ca");
-#else
-        CPPUNIT_ASSERT( ca_ES_valencia_Fallbacks.size() == 3);
-        CPPUNIT_ASSERT( ca_ES_valencia_Fallbacks[0] == "ca-ES-valencia");
-        CPPUNIT_ASSERT( ca_ES_valencia_Fallbacks[1] == "ca-ES");
-        CPPUNIT_ASSERT( ca_ES_valencia_Fallbacks[2] == "ca");
-#endif
         /* TODO: conversion doesn't know this yet, once it does activate test. */
 #if 0
         CPPUNIT_ASSERT( ca_ES_valencia.makeFallback().getBcp47() == "ca-ES-valencia");
@@ -189,8 +181,6 @@ void TestLanguageTag::testAllTags()
     }
 
     {
-        /* TODO: replacement doesn't handle variants yet. */
-#if USE_LIBLANGTAG
         OUString s_ca_valencia( "ca-valencia" );
         LanguageTag ca_valencia( s_ca_valencia, true );
         lang::Locale aLocale = ca_valencia.getLocale();
@@ -216,7 +206,6 @@ void TestLanguageTag::testAllTags()
 #else
         CPPUNIT_ASSERT( ca_valencia.makeFallback().getBcp47() == "ca-ES");
 #endif
-#endif
     }
 
     {
diff --git a/i18nlangtag/source/languagetag/simple-langtag.cxx b/i18nlangtag/source/languagetag/simple-langtag.cxx
index 153500a..a9588ea 100644
--- a/i18nlangtag/source/languagetag/simple-langtag.cxx
+++ b/i18nlangtag/source/languagetag/simple-langtag.cxx
@@ -95,7 +95,7 @@ struct my_t_impl : public my_ref
         else
             mpStr = NULL;
     }
-    void append( const char* str, const char* stop )
+    virtual void append( const char* str, const char* stop )
     {
         if (str && str < stop)
         {
@@ -110,7 +110,7 @@ struct my_t_impl : public my_ref
             mpStr = p;
         }
     }
-    void zero()
+    virtual void zero()
     {
         g_free( mpStr);
         mpStr = NULL;
@@ -162,8 +162,9 @@ struct lt_list_t : public my_t_impl
 
 static lt_pointer_t lt_list_value( const lt_list_t* p )
 {
-    // Assuming only char* here.
-    return p ? p->mpStr : NULL;
+    // This may look odd, but in this implementation the list element itself
+    // holds the char* mpStr to be obtained with lt_variant_get_tag()
+    return static_cast<lt_pointer_t>(const_cast<lt_list_t*>(p));
 }
 
 static const lt_list_t* lt_list_next( const lt_list_t* p )
@@ -201,24 +202,72 @@ static void my_unrefList( lt_list_t* pList )
     }
 }
 
+static void my_appendToList( lt_list_t** ppList, lt_list_t* pEntry )
+{
+    if (ppList)
+    {
+        if (!*ppList)
+            *ppList = pEntry;
+        else
+        {
+            lt_list_t* pThat = *ppList;
+            for (lt_list_t* pNext = pThat->mpNext; pNext; pNext = pThat->mpNext)
+                pThat = pNext;
+            pThat->mpNext = pEntry;
+            pEntry->mpPrev = pThat;
+        }
+    }
+}
+
+// my_t_impl has a superfluous mpStr here, but simplifies things much in the
+// parser.
+struct my_t_list : public my_t_impl
+{
+    lt_list_t* mpList;
+    explicit my_t_list() : my_t_impl(), mpList(NULL) {}
+    explicit my_t_list( const my_t_list& r ) : my_t_impl( r), mpList( my_copyList( r.mpList)) {}
+    virtual ~my_t_list()
+    {
+        my_unrefList( mpList);
+    }
+    my_t_list& operator=( const my_t_list& r )
+    {
+        if (this == &r)
+            return *this;
+        my_t_impl::operator=( r);
+        lt_list_t* pList = my_copyList( r.mpList);
+        my_unrefList( mpList);
+        mpList = pList;
+    }
+    virtual void append( const char* str, const char* stop )
+    {
+        lt_list_t* p = new lt_list_t;
+        p->assign( str, stop);
+        my_appendToList( &mpList, p);
+    }
+    virtual void zero()
+    {
+        my_t_impl::zero();
+        my_unrefList( mpList);
+        mpList = NULL;
+    }
+};
+
 struct lt_tag_t : public my_t_impl
 {
     lt_lang_t   maLanguage;
     lt_script_t maScript;
     lt_region_t maRegion;
-    lt_list_t*  mpVariants;
-    explicit lt_tag_t() : my_t_impl(), maLanguage(), maScript(), maRegion(), mpVariants(NULL) {}
-    virtual ~lt_tag_t()
-    {
-        my_unrefList( mpVariants);
-    }
+    my_t_list   maVariants;
+    explicit lt_tag_t() : my_t_impl(), maLanguage(), maScript(), maRegion(), maVariants() {}
+    virtual ~lt_tag_t() {}
     explicit lt_tag_t( const lt_tag_t& r )
         :
             my_t_impl( r),
             maLanguage( r.maLanguage),
             maScript( r.maScript),
             maRegion( r.maRegion),
-            mpVariants( my_copyList( r.mpVariants))
+            maVariants( r.maVariants)
     {
     }
     lt_tag_t& operator=( const lt_tag_t& r )
@@ -229,8 +278,7 @@ struct lt_tag_t : public my_t_impl
         maLanguage = r.maLanguage;
         maScript = r.maScript;
         maRegion = r.maRegion;
-        my_unrefList( mpVariants);
-        mpVariants = my_copyList( r.mpVariants);
+        maVariants = r.maVariants;
         return *this;
     }
     void assign( const char* str )
@@ -238,8 +286,7 @@ struct lt_tag_t : public my_t_impl
         maLanguage.zero();
         maScript.zero();
         maRegion.zero();
-        my_unrefList( mpVariants);
-        mpVariants = NULL;
+        maVariants.zero();
         my_t_impl::assign( str);
     }
 };
@@ -282,8 +329,7 @@ static lt_bool_t lt_tag_parse(lt_tag_t *tag,
     if (!tag_string)
         return 0;
     // In case we supported other subtags this would get more complicated.
-    /* TODO: variants */
-    my_t_impl* aSubtags[] = { &tag->maLanguage, &tag->maScript, &tag->maRegion, NULL };
+    my_t_impl* aSubtags[] = { &tag->maLanguage, &tag->maScript, &tag->maRegion, &tag->maVariants, NULL };
     my_t_impl** ppSub = &aSubtags[0];
     const char* pStart = tag_string;
     const char* p = pStart;
@@ -369,10 +415,13 @@ static lt_bool_t lt_tag_parse(lt_tag_t *tag,
                 {
                     case 4:
                         // script subtag, or a (DIGIT 3alphanum) variant with
-                        // no script and no region in which case we stop
-                        // parsing.
+                        // no script and no region
                         if ('0' <= *pStart && *pStart <= '9')
-                            ppSub = NULL;
+                        {
+                            ppSub += 2; // &tag->maVariants XXX watch this when inserting fields
+                            --p;
+                            continue;   // for
+                        }
                         else
                             (*ppSub++)->assign( pStart, p);
                         break;
@@ -404,9 +453,11 @@ static lt_bool_t lt_tag_parse(lt_tag_t *tag,
                     case 6:
                     case 7:
                     case 8:
-                        // script omitted, region omitted, variant subtag, stop
-                        // parsing.
-                        ppSub = NULL;
+                        // script omitted, region omitted, variant subtag
+                        ppSub += 2; // &tag->maVariants XXX watch this when inserting fields
+                        --p;
+                        continue;   // for
+                        break;
                     default:
                         return 0;   // bad
                 }
@@ -416,7 +467,35 @@ static lt_bool_t lt_tag_parse(lt_tag_t *tag,
                 if (nLen == 2 || nLen == 3)
                     (*ppSub++)->assign( pStart, p);
                 else
-                    return 0;   // bad
+                {
+                    // advance to variants
+                    ++ppSub;
+                    --p;
+                    continue;   // for
+                }
+            }
+            else if (*ppSub == &tag->maVariants)
+            {
+                // Stuff the remainder into variants, might not be correct, but ...
+                switch (nLen)
+                {
+                    case 4:
+                        // a (DIGIT 3alphanum) variant
+                        if ('0' <= *pStart && *pStart <= '9')
+                            ;   // nothing
+                        else
+                            return 0;   // bad
+                        break;
+                    case 5:
+                    case 6:
+                    case 7:
+                    case 8:
+                        ;   // nothing, variant
+                        break;
+                    default:
+                        return 0;   // bad
+                }
+                (*ppSub)->append( pStart, p);
             }
             pStart = p+1;
         }
@@ -448,7 +527,7 @@ static const lt_region_t *lt_tag_get_region(const lt_tag_t  *tag)
 
 static const lt_list_t *lt_tag_get_variants(const lt_tag_t  *tag)
 {
-    return tag ? tag->mpVariants : NULL;
+    return tag ? tag->maVariants.mpList : NULL;
 }
 
 static const char *lt_lang_get_tag(const lt_lang_t *lang)


More information about the Libreoffice-commits mailing list