diff --git a/Foundation/include/Poco/ListMap.h b/Foundation/include/Poco/ListMap.h index 3ca21d32c..235045b1e 100644 --- a/Foundation/include/Poco/ListMap.h +++ b/Foundation/include/Poco/ListMap.h @@ -41,6 +41,7 @@ #include "Poco/Foundation.h" +#include "Poco/String.h" #include "Poco/Exception.h" #include #include @@ -49,17 +50,15 @@ namespace Poco { -template > > +template >, bool CaseSensitive = false > class ListMap - /// This class implements a map in terms of a sequential container. + /// This class implements a multimap in terms of a sequential container. /// The use for this type of associative container is wherever automatic /// ordering of elements is not desirable. Naturally, this container will - /// have inferior data retrieval perofrmance and it is not recommended for + /// have inferior data retrieval performance and it is not recommended for /// use with large datasets. The main purpose within POCO is for Internet - /// messages (email in particular), in order to prevent autmomatic header - /// reordering. - /// - /// A ListMap can be used just like a std::map. + /// messages (email message, http headers etc), to prevent autmomatic + /// header entry reordering. { public: typedef Key KeyType; @@ -100,26 +99,34 @@ public: } ConstIterator begin() const + /// Returns the beginning of the map. { return _list.begin(); } ConstIterator end() const + /// Returns the end of the map. { return _list.end(); } Iterator begin() + /// Returns the beginning of the map. { return _list.begin(); } Iterator end() + /// Returns the end of the map. { return _list.end(); } ConstIterator find(const KeyType& key) const + /// Finds the first occurence of the key and + /// returns iterator pointing to the found entry + /// or iterator pointing to the end if entry is + /// not found. { Container::const_iterator it = _list.begin(); Container::const_iterator end = _list.end(); @@ -131,6 +138,10 @@ public: } Iterator find(const KeyType& key) + /// Finds the first occurence of the key and + /// returns iterator pointing to the found entry + /// or iterator pointing to the end if entry is + /// not found. { Container::iterator it = _list.begin(); Container::iterator end = _list.end(); @@ -141,12 +152,27 @@ public: return end; } - std::pair insert(const ValueType& val) + Iterator insert(const ValueType& val) + /// Inserts the value into the map. If one or more values + /// already exist, new value is inserted at the end of the + /// block. Thus, all the equal value entries are located + /// sequentially at all times. + /// Returns iterator pointing to the newly inserted value { - _list.push_back(val); - Iterator it = _list.end(); - std::pair p(--it, true); - return p; + Iterator it = find(val.first); + + if (it == _list.end()) + { + _list.push_back(val); + it = _list.end(); + --it; + } + else + { + _list.insert(it, 1, val); + } + + return it; } void erase(Iterator it) @@ -158,10 +184,20 @@ public: { SizeType count = 0; Iterator it = find(key); + bool removed = false; while (it != _list.end()) { - ++count; - it = _list.erase(it); + if (isEqual(it->first, key)) + { + ++count; + it = _list.erase(it); + removed = true; + } + else + { + if (removed) return count; + ++it; + } } return count; } @@ -197,8 +233,8 @@ public: return it->second; else { - _list.push_back(ValueType(key, KeyType())); - it = find(key); + ValueType value(key, Mapped()); + Iterator it = insert(value); return it->second; } } @@ -210,10 +246,27 @@ private: return val1 == val2; } - template <> bool isEqual(const std::string& s1, const std::string& s2) const { - return Poco::icompare(s1, s2) == 0; + if (!CaseSensitive) + return Poco::icompare(s1, s2) == 0; + else + return s1 == s2; + } + + bool isEqual(const std::string& s1, const char* s2) const + { + return isEqual(s1, std::string(s2)); + } + + bool isEqual(const char* s1, const std::string& s2) const + { + return isEqual(std::string(s1), s2); + } + + bool isEqual(const char* s1, const char* s2) const + { + return isEqual(std::string(s1), std::string(s2)); } Container _list; diff --git a/Foundation/testsuite/src/ListMapTest.cpp b/Foundation/testsuite/src/ListMapTest.cpp index 1476b9820..67d6447b9 100644 --- a/Foundation/testsuite/src/ListMapTest.cpp +++ b/Foundation/testsuite/src/ListMapTest.cpp @@ -62,10 +62,9 @@ void ListMapTest::testInsert() for (int i = 0; i < N; ++i) { - std::pair res = hm.insert(IntMap::ValueType(i, i*2)); - assert (res.first->first == i); - assert (res.first->second == i*2); - assert (res.second); + IntMap::Iterator res = hm.insert(IntMap::ValueType(i, i*2)); + assert (res->first == i); + assert (res->second == i*2); IntMap::Iterator it = hm.find(i); assert (it != hm.end()); assert (it->first == i); @@ -83,11 +82,12 @@ void ListMapTest::testInsert() assert (it->second == i*2); } + hm.clear(); for (int i = 0; i < N; ++i) { - std::pair res = hm.insert(IntMap::ValueType(i, 0)); - assert (res.first->first == i); - assert (res.first->second == 0); + IntMap::Iterator res = hm.insert(IntMap::ValueType(i, 0)); + assert (res->first == i); + assert (res->second == 0); } } @@ -192,7 +192,7 @@ void ListMapTest::testConstIterator() } -void ListMapTest::testIndex() +void ListMapTest::testIntIndex() { typedef ListMap IntMap; IntMap hm; @@ -218,6 +218,32 @@ void ListMapTest::testIndex() } +void ListMapTest::testStringIndex() +{ + typedef ListMap StringMap; + StringMap hm; + + hm["index1"] = "value2"; + hm["index2"] = "value4"; + hm["index3"] = "value6"; + + assert (hm.size() == 3); + assert (hm["index1"] == "value2"); + assert (hm["Index2"] == "value4"); + assert (hm["inDeX3"] == "value6"); + + try + { + const StringMap& im = hm; + std::string x = im["index4"]; + fail("no such key - must throw"); + } + catch (Poco::NotFoundException&) + { + } +} + + void ListMapTest::setUp() { } @@ -236,7 +262,8 @@ CppUnit::Test* ListMapTest::suite() CppUnit_addTest(pSuite, ListMapTest, testErase); CppUnit_addTest(pSuite, ListMapTest, testIterator); CppUnit_addTest(pSuite, ListMapTest, testConstIterator); - CppUnit_addTest(pSuite, ListMapTest, testIndex); + CppUnit_addTest(pSuite, ListMapTest, testIntIndex); + CppUnit_addTest(pSuite, ListMapTest, testStringIndex); return pSuite; } diff --git a/Foundation/testsuite/src/ListMapTest.h b/Foundation/testsuite/src/ListMapTest.h index 619648216..b2411aebb 100644 --- a/Foundation/testsuite/src/ListMapTest.h +++ b/Foundation/testsuite/src/ListMapTest.h @@ -50,7 +50,8 @@ public: void testErase(); void testIterator(); void testConstIterator(); - void testIndex(); + void testIntIndex(); + void testStringIndex(); void setUp(); void tearDown();