[Libreoffice-commits] core.git: Branch 'private/kohei/calc-shared-string' - 2 commits - include/svl svl/qa svl/source

Kohei Yoshida kohei.yoshida at collabora.com
Wed Oct 2 13:34:29 PDT 2013


 include/svl/stringpool.hxx     |   24 +++++++++++++++-
 svl/qa/unit/svl.cxx            |   22 ++++++++++++++-
 svl/source/misc/stringpool.cxx |   59 ++++++++++++++++++++++++++++++++++++++---
 3 files changed, 99 insertions(+), 6 deletions(-)

New commits:
commit b82477525d3fc2ffa553534743b89fa6e5ec1b5a
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Wed Oct 2 16:35:41 2013 -0400

    Add purge() method to purge unreferenced strings from the pool.
    
    But this code needs more work.
    
    Change-Id: I538eebf5eb1738a2cfeebc22052b3d5db6001b6b

diff --git a/include/svl/stringpool.hxx b/include/svl/stringpool.hxx
index d2eca12..cac7637 100644
--- a/include/svl/stringpool.hxx
+++ b/include/svl/stringpool.hxx
@@ -54,7 +54,8 @@ public:
 
     /**
      * Get a unique ID of string object that's expected to be in the shared
-     * string pool. If the string is not in the pool, NULL is returned.
+     * string pool. If the string is not in the pool, NULL is returned.  The
+     * ID obtained by this method can be used for case sensitive comparison.
      *
      * @param rStr string object to get the ID of.
      *
@@ -62,8 +63,27 @@ public:
      */
     StrIdType getIdentifier( const OUString& rStr ) const;
 
+    /**
+     * Get a unique ID of string object for case insensitive comparison. The
+     * string object is expected to be in the pool.
+     *
+     * @param rStr string object to get the ID of.
+     *
+     * @return unique ID of the string object usable for case insensitive
+     *         comparison.
+     */
     StrIdType getIdentifierIgnoreCase( const OUString& rStr ) const;
 
+    /**
+     * Go through all string objects in the pool, and clear those that are no
+     * longer used outside of the pool.
+     */
+    void purge();
+
+    size_t getCount() const;
+
+    size_t getCountIgnoreCase() const;
+
 private:
     InsertResultType findOrInsert( StrHashType& rPool, const OUString& rStr ) const;
 };
diff --git a/svl/qa/unit/svl.cxx b/svl/qa/unit/svl.cxx
index 58882bb..26cad83 100644
--- a/svl/qa/unit/svl.cxx
+++ b/svl/qa/unit/svl.cxx
@@ -36,7 +36,7 @@
 #include "svl/stringpool.hxx"
 #include "unotools/syslocale.hxx"
 
-#define DEBUG_UNIT_TEST 0
+#define DEBUG_UNIT_TEST 1
 
 #if DEBUG_UNIT_TEST
 #include <iostream>
@@ -68,12 +68,14 @@ public:
 
     void testNumberFormat();
     void testStringPool();
+    void testStringPoolPurge();
     void testFdo60915();
     void testI116701();
 
     CPPUNIT_TEST_SUITE(Test);
     CPPUNIT_TEST(testNumberFormat);
     CPPUNIT_TEST(testStringPool);
+//  CPPUNIT_TEST(testStringPoolPurge); // FIXME: String pool's life cycle needs more work.
     CPPUNIT_TEST(testFdo60915);
     CPPUNIT_TEST(testI116701);
     CPPUNIT_TEST_SUITE_END();
@@ -335,6 +337,24 @@ void Test::testStringPool()
     CPPUNIT_ASSERT_EQUAL(si1, si2);
 }
 
+void Test::testStringPoolPurge()
+{
+    SvtSysLocale aSysLocale;
+    svl::StringPool aPool(aSysLocale.GetCharClassPtr());
+    aPool.intern("Andy");
+    aPool.intern("andy");
+    aPool.intern("ANDY");
+
+    CPPUNIT_ASSERT_MESSAGE("Wrong string count.", aPool.getCount() == 3);
+    CPPUNIT_ASSERT_MESSAGE("Wrong case insensitive string count.", aPool.getCountIgnoreCase() == 1);
+
+    // Since no string objects referencing the pooled strings exist, purging
+    // the pool should empty it.
+    aPool.purge();
+    CPPUNIT_ASSERT_MESSAGE("Wrong string count.", aPool.getCount() == 0);
+    CPPUNIT_ASSERT_MESSAGE("Wrong case insensitive string count.", aPool.getCountIgnoreCase() == 0);
+}
+
 void Test::checkPreviewString(SvNumberFormatter& aFormatter,
                               const OUString& sCode,
                               double fPreviewNumber,
diff --git a/svl/source/misc/stringpool.cxx b/svl/source/misc/stringpool.cxx
index 11b6288..f4d9996 100644
--- a/svl/source/misc/stringpool.cxx
+++ b/svl/source/misc/stringpool.cxx
@@ -67,6 +67,60 @@ StringPool::StrIdType StringPool::getIdentifierIgnoreCase( const OUString& rStr
     return reinterpret_cast<StrIdType>(pUpper);
 }
 
+namespace {
+
+inline sal_Int32 getRefCount( const rtl_uString* p )
+{
+    return (p->refCount & 0x3FFFFFFF);
+}
+
+}
+
+void StringPool::purge()
+{
+    StrHashType aNewStrPool;
+    StrHashType::iterator it = maStrPool.begin(), itEnd = maStrPool.end();
+    for (; it != itEnd; ++it)
+    {
+        const rtl_uString* p = it->pData;
+        if (getRefCount(p) == 1)
+        {
+            // Remove it from the upper string map.  This should unref the
+            // upper string linked to this original string.
+            maToUpperMap.erase(p);
+        }
+        else
+            // Still referenced outside the pool. Keep it.
+            aNewStrPool.insert(*it);
+    }
+
+    maStrPool.swap(aNewStrPool);
+
+    aNewStrPool.clear(); // for re-use.
+
+    // Purge the upper string pool as well.
+    it = maStrPoolUpper.begin();
+    itEnd = maStrPoolUpper.end();
+    for (; it != itEnd; ++it)
+    {
+        const rtl_uString* p = it->pData;
+        if (getRefCount(p) > 1)
+            aNewStrPool.insert(*it);
+    }
+
+    maStrPoolUpper.swap(aNewStrPool);
+}
+
+size_t StringPool::getCount() const
+{
+    return maStrPool.size();
+}
+
+size_t StringPool::getCountIgnoreCase() const
+{
+    return maStrPoolUpper.size();
+}
+
 StringPool::InsertResultType StringPool::findOrInsert( StrHashType& rPool, const OUString& rStr ) const
 {
     StrHashType::iterator it = rPool.find(rStr);
commit dfcf3dc7dc6dd2acbb5b302c52429a30c0bc717a
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Wed Oct 2 14:06:13 2013 -0400

    The map actualy needs to store OUString to have it ref-counted automatically.
    
    Change-Id: Iff6fcf3aba73f2d06ac0c885b39e69ac0febc49f

diff --git a/include/svl/stringpool.hxx b/include/svl/stringpool.hxx
index 4436efe..d2eca12 100644
--- a/include/svl/stringpool.hxx
+++ b/include/svl/stringpool.hxx
@@ -29,7 +29,7 @@ class SVL_DLLPUBLIC StringPool
 {
     typedef boost::unordered_set<OUString, OUStringHash> StrHashType;
     typedef std::pair<StrHashType::iterator, bool> InsertResultType;
-    typedef boost::unordered_map<const rtl_uString*, const rtl_uString*> StrIdMapType;
+    typedef boost::unordered_map<const rtl_uString*, OUString> StrIdMapType;
 
     StrHashType maStrPool;
     StrHashType maStrPoolUpper;
diff --git a/svl/source/misc/stringpool.cxx b/svl/source/misc/stringpool.cxx
index 76dc4aa..11b6288 100644
--- a/svl/source/misc/stringpool.cxx
+++ b/svl/source/misc/stringpool.cxx
@@ -40,8 +40,7 @@ rtl_uString* StringPool::intern( const OUString& rStr )
         return pOrig;
 
     // Set mapping.
-    rtl_uString* pUpper = aRes.first->pData;
-    maToUpperMap.insert(StrIdMapType::value_type(pOrig, pUpper));
+    maToUpperMap.insert(StrIdMapType::value_type(pOrig, *aRes.first));
 
     return pOrig;
 }
@@ -64,7 +63,7 @@ StringPool::StrIdType StringPool::getIdentifierIgnoreCase( const OUString& rStr
         // Passed string is not in the pool.
         return 0;
 
-    const rtl_uString* pUpper = itUpper->second;
+    const rtl_uString* pUpper = itUpper->second.pData;
     return reinterpret_cast<StrIdType>(pUpper);
 }
 


More information about the Libreoffice-commits mailing list