mirror of
				https://github.com/pocoproject/poco.git
				synced 2025-10-30 05:29:41 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			266 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			266 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| //
 | |
| // ListMap.h
 | |
| //
 | |
| // Library: Foundation
 | |
| // Package: Core
 | |
| // Module:  ListMap
 | |
| //
 | |
| // Definition of the ListMap class.
 | |
| //
 | |
| // Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
 | |
| // and Contributors.
 | |
| //
 | |
| // SPDX-License-Identifier:	BSL-1.0
 | |
| //
 | |
| 
 | |
| 
 | |
| #ifndef Foundation_ListMap_INCLUDED
 | |
| #define Foundation_ListMap_INCLUDED
 | |
| 
 | |
| 
 | |
| #include "Poco/Foundation.h"
 | |
| #include "Poco/String.h"
 | |
| #include "Poco/Exception.h"
 | |
| #include <vector>
 | |
| #include <utility>
 | |
| 
 | |
| 
 | |
| namespace Poco {
 | |
| 
 | |
| 
 | |
| template <class Key, class Mapped, class Container = std::vector<std::pair<Key, Mapped>>, bool CaseSensitive = false>
 | |
| class ListMap
 | |
| 	/// 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 performance and it is not recommended for
 | |
| 	/// use with large datasets. The main purpose within POCO is for Internet
 | |
| 	/// messages (email message, http headers etc), to prevent automatic 
 | |
| 	/// header entry reordering.
 | |
| {
 | |
| public:
 | |
| 	using KeyType = Key;
 | |
| 	using MappedType = Mapped;
 | |
| 	using Reference = Mapped&;
 | |
| 	using ConstReference = const Mapped&;
 | |
| 	using Pointer = Mapped*;
 | |
| 	using ConstPointer = const Mapped*;
 | |
| 	
 | |
| 	using ValueType = typename Container::value_type;
 | |
| 	using SizeType = typename Container::size_type;
 | |
| 	using Iterator = typename Container::iterator;
 | |
| 	using ConstIterator = typename Container::const_iterator;
 | |
| 	
 | |
| 	ListMap()
 | |
| 		/// Creates an empty ListMap.
 | |
| 	{
 | |
| 	}
 | |
| 	
 | |
| 	explicit ListMap(std::size_t initialReserve):
 | |
| 		_container(initialReserve)
 | |
| 		/// Creates the ListMap with room for initialReserve entries.
 | |
| 	{
 | |
| 	}
 | |
| 
 | |
| 	ListMap(const ListMap& other):
 | |
| 		_container(other._container)
 | |
| 	{
 | |
| 	}
 | |
| 
 | |
| 	ListMap(ListMap&& other) noexcept:
 | |
| 		_container(std::move(other._container))
 | |
| 	{
 | |
| 	}
 | |
| 	
 | |
| 	ListMap& operator = (const ListMap& map)
 | |
| 		/// Assigns another ListMap.
 | |
| 	{
 | |
| 		ListMap tmp(map);
 | |
| 		swap(tmp);
 | |
| 		return *this;
 | |
| 	}
 | |
| 	
 | |
| 	ListMap& operator = (ListMap&& map) noexcept
 | |
| 		/// Assigns another ListMap.
 | |
| 	{
 | |
| 		_container = std::move(map._container);
 | |
| 		return *this;
 | |
| 	}
 | |
| 	
 | |
| 	void swap(ListMap& map)
 | |
| 		/// Swaps the ListMap with another one.
 | |
| 	{
 | |
| 		_container.swap(map._container);
 | |
| 	}
 | |
| 	
 | |
| 	ConstIterator begin() const
 | |
| 		/// Returns the beginning of the map.
 | |
| 	{
 | |
| 		return _container.begin();
 | |
| 	}
 | |
| 	
 | |
| 	ConstIterator end() const
 | |
| 		/// Returns the end of the map.
 | |
| 	{
 | |
| 		return _container.end();
 | |
| 	}
 | |
| 	
 | |
| 	Iterator begin()
 | |
| 		/// Returns the beginning of the map.
 | |
| 	{
 | |
| 		return _container.begin();
 | |
| 	}
 | |
| 	
 | |
| 	Iterator end()
 | |
| 		/// Returns the end of the map.
 | |
| 	{
 | |
| 		return _container.end();
 | |
| 	}
 | |
| 	
 | |
| 	ConstIterator find(const KeyType& key) const
 | |
| 		/// Finds the first occurrence of the key and
 | |
| 		/// returns iterator pointing to the found entry
 | |
| 		/// or iterator pointing to the end if entry is
 | |
| 		/// not found.
 | |
| 	{
 | |
| 		typename Container::const_iterator it = _container.begin();
 | |
| 		typename Container::const_iterator itEnd = _container.end();
 | |
| 		for(; it != itEnd; ++it)
 | |
| 		{
 | |
| 			if (isEqual(it->first, key)) return it;
 | |
| 		}
 | |
| 		return itEnd;
 | |
| 	}
 | |
| 
 | |
| 	Iterator find(const KeyType& key)
 | |
| 		/// Finds the first occurrence of the key and
 | |
| 		/// returns iterator pointing to the found entry
 | |
| 		/// or iterator pointing to the end if entry is
 | |
| 		/// not found.
 | |
| 	{
 | |
| 		typename Container::iterator it = _container.begin();
 | |
| 		typename Container::iterator itEnd = _container.end();
 | |
| 		for(; it != itEnd; ++it)
 | |
| 		{
 | |
| 			if (isEqual(it->first, key)) return it;
 | |
| 		}
 | |
| 		return itEnd;
 | |
| 	}
 | |
| 
 | |
| 	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 
 | |
| 	{
 | |
| 		Iterator it = find(val.first);
 | |
| 		while (it != _container.end() && isEqual(it->first, val.first)) ++it;
 | |
| 		return _container.insert(it, val);
 | |
| 	}
 | |
| 	
 | |
| 	void erase(Iterator it)
 | |
| 	{
 | |
| 		_container.erase(it);
 | |
| 	}
 | |
| 	
 | |
| 	SizeType erase(const KeyType& key)
 | |
| 	{
 | |
| 		SizeType count = 0;
 | |
| 		Iterator it = find(key);
 | |
| 		bool removed = false;
 | |
| 		while (it != _container.end())
 | |
| 		{
 | |
| 			if (isEqual(it->first, key))
 | |
| 			{
 | |
| 				++count;
 | |
| 				it = _container.erase(it);
 | |
| 				removed = true;
 | |
| 			}
 | |
| 			else
 | |
| 			{
 | |
| 				if (removed) return count;
 | |
| 				++it;
 | |
| 			}
 | |
| 		}
 | |
| 		return count;
 | |
| 	}
 | |
| 	
 | |
| 	void clear()
 | |
| 	{
 | |
| 		_container.clear();
 | |
| 	}
 | |
| 
 | |
| 	std::size_t size() const
 | |
| 	{
 | |
| 		return _container.size();
 | |
| 	}
 | |
| 
 | |
| 	bool empty() const
 | |
| 	{
 | |
| 		return _container.empty();
 | |
| 	}
 | |
| 
 | |
| 	ConstReference operator [] (const KeyType& key) const
 | |
| 	{
 | |
| 		ConstIterator it = find(key);
 | |
| 		if (it != _container.end())
 | |
| 			return it->second;
 | |
| 		else
 | |
| 			throw NotFoundException();
 | |
| 	}
 | |
| 
 | |
| 	Reference operator [] (const KeyType& key)
 | |
| 	{
 | |
| 		Iterator it = find(key);
 | |
| 		if (it != _container.end())
 | |
| 		{
 | |
| 			return it->second;
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			ValueType value(key, Mapped());
 | |
| 			Iterator itInsert = insert(value);
 | |
| 			return itInsert->second;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| private:
 | |
| 	template <typename T1, typename T2>
 | |
| 	bool isEqual(T1 val1, T2 val2) const
 | |
| 	{
 | |
| 		return val1 == val2;
 | |
| 	}
 | |
| 
 | |
| 	bool isEqual(const std::string& s1, const std::string& s2) const
 | |
| 	{
 | |
| 		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 _container;
 | |
| };
 | |
| 
 | |
| 
 | |
| } // namespace Poco
 | |
| 
 | |
| 
 | |
| #endif // Foundation_ListMap_INCLUDED
 | 
