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 <[email protected]> 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 <[email protected]> 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); } _______________________________________________ Libreoffice-commits mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
