diff options
-rw-r--r-- | include/svl/stringpool.hxx | 37 | ||||
-rw-r--r-- | svl/source/misc/stringpool.cxx | 51 |
2 files changed, 83 insertions, 5 deletions
diff --git a/include/svl/stringpool.hxx b/include/svl/stringpool.hxx index 643c8466c0bc..25415684c9fd 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 f8ddda9b0acd..46462d1e7a59 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); } } |