[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 08:28:57 PDT 2013
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.yoshida at 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.yoshida at 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);
}
}
More information about the Libreoffice-commits
mailing list