/* ///////////////////////////////////////////////////////////////////////// * File: stlsoft/containers/frequency_map.hpp * * Purpose: A container that measures the frequency of the unique elements it contains. * * Created: 1st October 2005 * Updated: 27th June 2011 * * Home: http://stlsoft.org/ * * Copyright (c) 2005-2011, Matthew Wilson and Synesis Software * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of * any contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * ////////////////////////////////////////////////////////////////////// */ /** \file stlsoft/containers/frequency_map.hpp * * \brief [C++ only] Definition of the stlsoft::frequency_map container * class template * (\ref group__library__containers "Containers" Library). */ #ifndef STLSOFT_INCL_STLSOFT_CONTAINERS_HPP_FREQUENCY_MAP #define STLSOFT_INCL_STLSOFT_CONTAINERS_HPP_FREQUENCY_MAP #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION # define STLSOFT_VER_STLSOFT_CONTAINERS_HPP_FREQUENCY_MAP_MAJOR 2 # define STLSOFT_VER_STLSOFT_CONTAINERS_HPP_FREQUENCY_MAP_MINOR 6 # define STLSOFT_VER_STLSOFT_CONTAINERS_HPP_FREQUENCY_MAP_REVISION 1 # define STLSOFT_VER_STLSOFT_CONTAINERS_HPP_FREQUENCY_MAP_EDIT 29 #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */ /* ///////////////////////////////////////////////////////////////////////// * Auto-generation and compatibility */ /* ///////////////////////////////////////////////////////////////////////// * Includes */ #ifndef STLSOFT_INCL_STLSOFT_H_STLSOFT # include #endif /* !STLSOFT_INCL_STLSOFT_H_STLSOFT */ #ifndef STLSOFT_INCL_STLSOFT_COLLECTIONS_UTIL_HPP_COLLECTIONS # include #endif /* !STLSOFT_INCL_STLSOFT_COLLECTIONS_UTIL_HPP_COLLECTIONS */ #ifndef STLSOFT_INCL_STLSOFT_META_HPP_IS_INTEGRAL_TYPE # include #endif /* !STLSOFT_INCL_STLSOFT_META_HPP_IS_INTEGRAL_TYPE */ #ifndef STLSOFT_INCL_STLSOFT_UTIL_HPP_STD_SWAP # include #endif /* !STLSOFT_INCL_STLSOFT_UTIL_HPP_STD_SWAP */ #ifndef STLSOFT_INCL_MAP # define STLSOFT_INCL_MAP # include #endif /* !STLSOFT_INCL_MAP */ /* ///////////////////////////////////////////////////////////////////////// * Namespace */ #ifndef _STLSOFT_NO_NAMESPACE namespace stlsoft { #endif /* _STLSOFT_NO_NAMESPACE */ /* ///////////////////////////////////////////////////////////////////////// * Classes */ /** A container that measures the frequency of the unique elements it * contains. * * \ingroup group__library__containers * * \param T The value type of the container * \param N The count integer type. Defaults to uint32_t */ template< ss_typename_param_k T #if defined(STLSOFT_COMPILER_IS_MSVC) && \ _MSC_VER < 1300 , ss_typename_param_k N = unsigned int #else , ss_typename_param_k N = uint32_t #endif , ss_typename_param_k P = stlsoft_ns_qual_std(less) > class frequency_map : public stl_collection_tag { private: // Member Types typedef stlsoft_ns_qual_std(map) map_type_; public: /// This type typedef frequency_map class_type; /// The value type typedef ss_typename_param_k map_type_::value_type value_type; /// The non-mutating (const) iterator type typedef ss_typename_param_k map_type_::const_iterator const_iterator; // typedef ss_typename_param_k map_type_::const_pointer const_pointer; /// The non-mutating (const) reverse iterator type typedef ss_typename_param_k map_type_::const_reverse_iterator const_reverse_iterator; /// The non-mutating (const) reference type typedef ss_typename_param_k map_type_::const_reference const_reference; /// The key type typedef ss_typename_param_k map_type_::key_type key_type; // typedef ss_typename_param_k map_type_::mapped_type mapped_type /// The count type typedef N count_type; /// The size type typedef ss_size_t size_type; /// The difference type typedef ss_ptrdiff_t difference_type; /// The boolean type typedef ss_bool_t bool_type; public: // Construction /// Creates an instance of the map frequency_map() : m_map() , m_total(0) { STLSOFT_STATIC_ASSERT(0 != stlsoft::is_integral_type::value); STLSOFT_ASSERT(is_valid()); } public: // Modifiers /// Pushes an entry onto the map /// /// If the entry already exists in the map, its count will be increased /// by 1. If it does not previously exist, it will be added with an /// initial count of one /// /// \note Thread-safety: it is strongly exception-safe - if an /// entry cannot be added, count_type push(key_type const& key) { STLSOFT_ASSERT(is_valid()); count_type r = ++m_map[key]; #if 0 // NOTE: Because the count type N must be an integer, the code above // is equivalent to the following "full" exception-safe implementation. ss_typename_param_k map_type_::iterator it = m_map.find(key); if(m_map.end() == it) { value_type value(key, 1); m_map.insert(value); return 1; } else { value_type& value = *it; return ++(*it).second; } #endif /* 0 */ ++m_total; STLSOFT_ASSERT(is_valid()); return r; } void push_n( key_type const& key , count_type n ) { // TODO: update this to a single action { for(count_type i = 0; i != n; ++i) { push(key); }} } /// Removes all entries from the map void clear() { STLSOFT_ASSERT(is_valid()); m_map.clear(); m_total = 0u; STLSOFT_ASSERT(is_valid()); } /// Merges in all entries from the given map class_type& merge(class_type const& rhs) { STLSOFT_ASSERT(is_valid()); class_type t(*this); { for(const_iterator i = rhs.begin(); i != rhs.end(); ++i) { t.m_map[(*i).first] += (*i).second; }} t.m_total += rhs.m_total; t.swap(*this); STLSOFT_ASSERT(is_valid()); return *this; } class_type& operator +=(class_type const& rhs) { return merge(rhs); } /// Swaps the state of the given instance with this instance void swap(class_type& rhs) stlsoft_throw_0() { STLSOFT_ASSERT(is_valid()); std_swap(m_map, rhs.m_map); std_swap(m_total, rhs.m_total); STLSOFT_ASSERT(is_valid()); } public: // Search /// Returns an iterator for the entry representing the given key, or /// end() if no such entry exists. const_iterator find(key_type const& key) const { STLSOFT_ASSERT(is_valid()); return m_map.find(key); } public: // Element Access /// Returns the count associated with the entry representing the given /// key, or 0 if no such entry exists. count_type operator [](key_type const& key) const { STLSOFT_ASSERT(is_valid()); return count(key); } /// Returns the count associated with the entry representing the given /// key, or 0 if no such entry exists. count_type count(key_type const& key) const { STLSOFT_ASSERT(is_valid()); const_iterator it = m_map.find(key); return (m_map.end() != it) ? (*it).second : 0; } public: // Size /// Indicates whether the map is empty bool_type empty() const { STLSOFT_ASSERT(is_valid()); return m_map.empty(); } /// The number of unique entries in the map /// /// \remarks This may not be the same as the number of calls to /// push() size_type size() const { STLSOFT_ASSERT(is_valid()); return m_map.size(); } /// The number of non-unique entries in the map /// /// \remarks This may not be the same as the number of calls to /// push() count_type total() const { STLSOFT_ASSERT(is_valid()); return m_total; } public: // Iteration /// A non-mutating (const) iterator representing the start of the sequence const_iterator begin() const { STLSOFT_ASSERT(is_valid()); return m_map.begin(); } /// A non-mutating (const) iterator representing the end-point of the sequence const_iterator end() const { STLSOFT_ASSERT(is_valid()); return m_map.end(); } /// A non-mutating (const) iterator representing the start of the reverse sequence const_reverse_iterator rbegin() const { STLSOFT_ASSERT(is_valid()); return m_map.rbegin(); } /// A non-mutating (const) iterator representing the end of the reverse sequence const_reverse_iterator rend() const { STLSOFT_ASSERT(is_valid()); return m_map.rend(); } private: bool is_valid() const { return m_map.empty() == (0u == m_total); } private: // Member Variables map_type_ m_map; count_type m_total; }; /* ///////////////////////////////////////////////////////////////////////// * Operators */ template< ss_typename_param_k T , ss_typename_param_k N , ss_typename_param_k P > inline frequency_map operator +( frequency_map const& lhs , frequency_map const& rhs ) { frequency_map r(lhs); r += rhs; return r; } /* ///////////////////////////////////////////////////////////////////////// * Swapping */ #if !defined(STLSOFT_COMPILER_IS_WATCOM) template< ss_typename_param_k T , ss_typename_param_k N , ss_typename_param_k P > inline void swap( frequency_map& lhs , frequency_map& rhs ) { lhs.swap(rhs); } #endif /* compiler */ /* ///////////////////////////////////////////////////////////////////////// * Unit-testing */ #ifdef STLSOFT_UNITTEST # include "./unittest/frequency_map_unittest_.h" #endif /* STLSOFT_UNITTEST */ /* ////////////////////////////////////////////////////////////////////// */ #ifndef _STLSOFT_NO_NAMESPACE } // namespace stlsoft #endif /* _STLSOFT_NO_NAMESPACE */ #if defined(STLSOFT_CF_std_NAMESPACE) namespace std { # if !defined(STLSOFT_COMPILER_IS_MSVC) || \ _MSC_VER >= 1310 template< ss_typename_param_k T , ss_typename_param_k N , ss_typename_param_k P > inline void swap( stlsoft_ns_qual(frequency_map)& lhs , stlsoft_ns_qual(frequency_map)& rhs ) { lhs.swap(rhs); } # endif } /* namespace std */ #endif /* STLSOFT_CF_std_NAMESPACE */ /* ////////////////////////////////////////////////////////////////////// */ #endif /* !STLSOFT_INCL_STLSOFT_CONTAINERS_HPP_FREQUENCY_MAP */ /* ///////////////////////////// end of file //////////////////////////// */