include/svl/stringpool.hxx | 39 ++++++++++++++++++++++++++ svl/qa/unit/svl.cxx | 40 ++++++++++++++++++++++++++ svl/source/misc/stringpool.cxx | 61 +++++++++++++++++++++++++++++++++++++---- 3 files changed, 135 insertions(+), 5 deletions(-)
New commits: commit 9f4dd5493dcf7b697896a1bf6fb078e76b081246 Author: Kohei Yoshida <kohei.yosh...@collabora.com> Date: Wed Oct 2 11:29:42 2013 -0400 Write some rudimentary tests for the new shared string pool class. Change-Id: Ie66de46d69f664839aa0a2d056cd3b8df4d4989b diff --git a/include/svl/stringpool.hxx b/include/svl/stringpool.hxx index 2541568..26785e3 100644 --- a/include/svl/stringpool.hxx +++ b/include/svl/stringpool.hxx @@ -34,11 +34,11 @@ class SVL_DLLPUBLIC StringPool StrHashType maStrPool; StrHashType maStrPoolUpper; StrIdMapType maToUpperMap; - CharClass* mpCharClass; + const CharClass* mpCharClass; public: StringPool(); - StringPool( CharClass* pCharClass ); + StringPool( const CharClass* pCharClass ); /** * Intern a string object into the shared string pool. @@ -60,6 +60,8 @@ public: */ const rtl_uString* getIdentifier( const OUString& rStr ) const; + const rtl_uString* getIdentifierIgnoreCase( const OUString& rStr ) 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 8d46ecf..f41ab73 100644 --- a/svl/qa/unit/svl.cxx +++ b/svl/qa/unit/svl.cxx @@ -33,6 +33,8 @@ #include "svl/zforlist.hxx" #include "svl/zformat.hxx" +#include "svl/stringpool.hxx" +#include "unotools/syslocale.hxx" #define DEBUG_UNIT_TEST 0 @@ -65,11 +67,13 @@ public: virtual void tearDown(); void testNumberFormat(); + void testStringPool(); void testFdo60915(); void testI116701(); CPPUNIT_TEST_SUITE(Test); CPPUNIT_TEST(testNumberFormat); + CPPUNIT_TEST(testStringPool); CPPUNIT_TEST(testFdo60915); CPPUNIT_TEST(testI116701); CPPUNIT_TEST_SUITE_END(); @@ -288,6 +292,42 @@ void Test::testNumberFormat() } } +void Test::testStringPool() +{ + SvtSysLocale aSysLocale; + svl::StringPool aPool(aSysLocale.GetCharClassPtr()); + + const rtl_uString* p1 = aPool.intern("Andy"); + const rtl_uString* p2 = aPool.intern("Andy"); + CPPUNIT_ASSERT_EQUAL(p1, p2); + + p2 = aPool.intern("Bruce"); + CPPUNIT_ASSERT_MESSAGE("They must differ.", p1 != p2); + + OUString aAndy("Andy"); + p2 = aPool.getIdentifier(aAndy); + CPPUNIT_ASSERT_EQUAL(p1, p2); + + // Test case insensitive string ID's. + OUString aAndyLower("andy"), aAndyUpper("ANDY"); + p1 = aPool.getIdentifier("Andy"); + CPPUNIT_ASSERT_MESSAGE("This shouldn't be NULL.", p1); + p2 = aPool.intern(aAndyLower); + CPPUNIT_ASSERT_MESSAGE("They must differ.", p1 != p2); + p2 = aPool.intern(aAndyUpper); + CPPUNIT_ASSERT_MESSAGE("They must differ.", p1 != p2); + + p1 = aPool.getIdentifierIgnoreCase("Andy"); + CPPUNIT_ASSERT_MESSAGE("This shouldn't be NULL.", p1); + p2 = aPool.getIdentifierIgnoreCase("andy"); + CPPUNIT_ASSERT_MESSAGE("This shouldn't be NULL.", p2); + CPPUNIT_ASSERT_EQUAL(p1, p2); + + p2 = aPool.getIdentifierIgnoreCase("ANDY"); + CPPUNIT_ASSERT_MESSAGE("This shouldn't be NULL.", p2); + CPPUNIT_ASSERT_EQUAL(p1, p2); +} + 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 46462d1..1181538 100644 --- a/svl/source/misc/stringpool.cxx +++ b/svl/source/misc/stringpool.cxx @@ -13,7 +13,7 @@ namespace svl { StringPool::StringPool() : mpCharClass(NULL) {} -StringPool::StringPool( CharClass* pCharClass ) : mpCharClass(pCharClass) {} +StringPool::StringPool( const CharClass* pCharClass ) : mpCharClass(pCharClass) {} rtl_uString* StringPool::intern( const OUString& rStr ) { @@ -52,6 +52,16 @@ const rtl_uString* StringPool::getIdentifier( const OUString& rStr ) const return (it == maStrPool.end()) ? NULL : it->pData; } +const rtl_uString* StringPool::getIdentifierIgnoreCase( const OUString& rStr ) const +{ + if (!mpCharClass) + return NULL; + + OUString aUpper = mpCharClass->uppercase(rStr); + StrHashType::iterator it = maStrPoolUpper.find(aUpper); + return (it == maStrPool.end()) ? NULL : it->pData; +} + StringPool::InsertResultType StringPool::findOrInsert( StrHashType& rPool, const OUString& rStr ) const { StrHashType::iterator it = rPool.find(rStr); commit 93d8f0172232a246e7b2a4d43ceddaf499837746 Author: Kohei Yoshida <kohei.yosh...@collabora.com> Date: Wed Oct 2 10:47:28 2013 -0400 Establish mapping between original strings and upper strings. This will be used to retrieve case insensitive string identifiers later. Change-Id: Ia34f57d0e8d0cb6bd4630f8d110853ed049770b5 diff --git a/include/svl/stringpool.hxx b/include/svl/stringpool.hxx index 643c846..2541568 100644 --- a/include/svl/stringpool.hxx +++ b/include/svl/stringpool.hxx @@ -13,18 +13,55 @@ #include "svl/svldllapi.h" #include "rtl/ustring.hxx" +#include <boost/unordered_map.hpp> #include <boost/unordered_set.hpp> +class CharClass; + namespace svl { +/** + * Storage for pool of shared strings. It also provides mapping from + * original-cased strings to upper-cased strings for case insensitive + * operations. + */ 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; + StrHashType maStrPool; + StrHashType maStrPoolUpper; + StrIdMapType maToUpperMap; + CharClass* mpCharClass; + public: StringPool(); + StringPool( CharClass* pCharClass ); + /** + * Intern a string object into the shared string pool. + * + * @param rStr string object to intern. + * + * @return a pointer to the string object stored inside the pool, or NULL + * if the insertion fails. + */ rtl_uString* intern( const OUString& rStr ); + + /** + * 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. + * + * @param rStr string object to get the ID of. + * + * @return unique ID of the string object. + */ + const rtl_uString* getIdentifier( const OUString& rStr ) const; + +private: + InsertResultType findOrInsert( StrHashType& rPool, const OUString& rStr ) const; }; } diff --git a/svl/source/misc/stringpool.cxx b/svl/source/misc/stringpool.cxx index f8ddda9..46462d1 100644 --- a/svl/source/misc/stringpool.cxx +++ b/svl/source/misc/stringpool.cxx @@ -8,26 +8,67 @@ */ #include "svl/stringpool.hxx" +#include "unotools/charclass.hxx" namespace svl { -StringPool::StringPool() {} +StringPool::StringPool() : mpCharClass(NULL) {} +StringPool::StringPool( CharClass* pCharClass ) : mpCharClass(pCharClass) {} rtl_uString* StringPool::intern( const OUString& rStr ) { + InsertResultType aRes = findOrInsert(maStrPool, rStr); + if (aRes.first == maStrPool.end()) + // Insertion failed. + return NULL; + + rtl_uString* pOrig = aRes.first->pData; + + if (!aRes.second) + // No new string has been inserted. Return the existing string in the pool. + return pOrig; + + if (!mpCharClass) + return pOrig; + + // This is a new string insertion. Establish mapping to upper-case variant. + + OUString aUpper = mpCharClass->uppercase(rStr); + aRes = findOrInsert(maStrPoolUpper, aUpper); + if (aRes.first == maStrPoolUpper.end()) + // Failed to insert or fetch upper-case variant. Should never happen. + return pOrig; + + // Set mapping. + rtl_uString* pUpper = aRes.first->pData; + maToUpperMap.insert(StrIdMapType::value_type(pOrig, pUpper)); + + return pOrig; +} + +const rtl_uString* StringPool::getIdentifier( const OUString& rStr ) const +{ StrHashType::iterator it = maStrPool.find(rStr); - if (it == maStrPool.end()) + return (it == maStrPool.end()) ? NULL : it->pData; +} + +StringPool::InsertResultType StringPool::findOrInsert( StrHashType& rPool, const OUString& rStr ) const +{ + StrHashType::iterator it = rPool.find(rStr); + bool bInserted = false; + if (it == rPool.end()) { // Not yet in the pool. - std::pair<StrHashType::iterator, bool> r = maStrPool.insert(rStr.intern()); + std::pair<StrHashType::iterator, bool> r = rPool.insert(rStr.intern()); if (!r.second) // Insertion failed. - return NULL; + return InsertResultType(rPool.end(), false); it = r.first; + bInserted = true; } - return it->pData; + return InsertResultType(it, bInserted); } } _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits