TinyMap.h
Upload User: geng8029
Upload Date: 2021-01-30
Package Size: 187k
Code Size: 7k
Category:

Audio program

Development Platform:

Visual C++

  1. //-----------------------------------------------------------------------------
  2. // File: TinyMap.h
  3. // Desc: Simple associative container class.
  4. //
  5. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  6. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  7. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  8. // PARTICULAR PURPOSE.
  9. //
  10. //  Copyright (C) Microsoft Corporation. All rights reserved.
  11. //-----------------------------------------------------------------------------
  12. // NOTES:
  13. // The TinyMap class is designed to hold a small-ish number of elements where
  14. // look-up performance is not important. (It uses a sorted linked list.)
  15. // 
  16. // TinyMap uses "copy semantics" (keys and values are copied into the map).
  17. // Keys must support the comparison operators.
  18. #pragma once
  19. #include "linklist.h"
  20. namespace MediaFoundationSamples
  21. {
  22.     template <class Key, class Value>
  23.     struct Pair
  24.     {
  25.         Key key;
  26.         Value value;
  27.         Pair() {}
  28.         Pair(Key k, Value v)
  29.         {
  30.             key = k;
  31.             value = v;
  32.         }
  33.     };
  34.     template <class Key, class Value>
  35.     class TinyMap : List< Pair<Key, Value> >
  36.     {
  37.     protected:
  38.         typedef Pair<Key, Value> pair_type;
  39.     public:
  40.         TinyMap()
  41.         {
  42.             Clear();
  43.         }
  44.         virtual ~TinyMap()
  45.         {
  46.         }
  47.         HRESULT Insert(Key k, Value v)
  48.         {
  49.             HRESULT hr = S_OK;
  50.             Node *pNode = Front();
  51.             while (TRUE)
  52.             {
  53.                 if (pNode == &m_anchor)
  54.                 {
  55.                     // Reached the end of the list. Insert at end.
  56.                     hr = InsertBack(pair_type(k, v));
  57.                     break;
  58.                 }
  59.                 else if (pNode->item.key == k)
  60.                 {
  61.                     // Found a duplicate item. Fail.
  62.                     hr = MF_E_INVALID_KEY; 
  63.                     break;
  64.                 }
  65.                 else if (pNode->item.key > k)
  66.                 {
  67.                     // Found a larger key. Insert before this item.
  68.                     hr = InsertAfter(pair_type(k, v), pNode->prev);
  69.                     break;
  70.                 }
  71.                 pNode = pNode->next;
  72.             }
  73.             return hr;
  74.         }
  75.         HRESULT Remove(Key k)
  76.         {
  77.             HRESULT hr = E_FAIL;
  78.             Node *pNode = Front();
  79.             Node *pToRemove = NULL;
  80.             // Delete the nodes
  81.             while (TRUE)
  82.             {
  83.                 if (pNode == &m_anchor)
  84.                 {
  85.                     // Reached the end of the list. 
  86.                     break;
  87.                 }
  88.                 else if (pNode->item.key == k)
  89.                 {
  90.                     // Found the node to remove.
  91.                     pToRemove = pNode; 
  92.                     break;
  93.                 }
  94.                 else if (pNode->item.key > k)
  95.                 {
  96.                     // Found a larger key. The item is not on the list.
  97.                     hr = MF_E_INVALID_KEY;
  98.                     break;
  99.                 }
  100.                 pNode = pNode->next;
  101.             }
  102.             if (pToRemove)
  103.             {
  104.                 hr = RemoveItem(pToRemove, NULL);
  105.             }
  106.             return hr;
  107.         }
  108.         // Find: Search the map for "k" and return the value in pv.
  109.         // pv can be NULL if you don't want to get the value back.
  110.         HRESULT Find(Key k, Value *pv)
  111.         {
  112.             HRESULT hr = S_OK;
  113.             BOOL bFound = FALSE;
  114.             pair_type pair;
  115.             POSITION pos = List<pair_type>::FrontPosition();
  116.             while (pos != List<pair_type>::EndPosition())
  117.             {
  118.                 hr = GetItemPos(pos, &pair);
  119.                 if (FAILED(hr))
  120.                 {
  121.                     break;
  122.                 }
  123.                 if (pair.key == k)
  124.                 {
  125.                     // Found a match
  126.                     if (pv)
  127.                     {
  128.                         *pv = pair.value; 
  129.                     }
  130.                     bFound = TRUE;
  131.                     break;
  132.                 }
  133.                 if (pair.key > k)
  134.                 {
  135.                     // Reached a larger key. Item not found.
  136.                     break;
  137.                 }
  138.                 pos = List<pair_type>::Next(pos);
  139.             }
  140.             return (bFound ? S_OK : MF_E_INVALID_KEY);
  141.         }
  142.         void Clear()
  143.         {
  144.             List<pair_type>::Clear();
  145.         }
  146.         // ClearValues
  147.         // Clear the list, using a defined function to free the values.
  148.         //
  149.         // clear_fn: Functor object whose operator() frees the *values* on the list.
  150.         //
  151.         // NOTE: This function assumes that the keys do not require special handling.
  152.         template <class FN>
  153.         void ClearValues(FN& clear_fn)
  154.         {
  155.             Node *n = m_anchor.next;
  156.             // Delete the nodes
  157.             while (n != &m_anchor)
  158.             {
  159.                 clear_fn(n->item.value);
  160.                 Node *tmp = n->next;
  161.                 delete n;
  162.                 n = tmp;
  163.             }
  164.             // Reset the anchor to point at itself
  165.             m_anchor.next = &m_anchor;
  166.             m_anchor.prev = &m_anchor;
  167.             m_count = 0;
  168.         }
  169.         DWORD GetCount() const 
  170.         {
  171.             return List<pair_type>::GetCount();
  172.         }
  173.     
  174.         ////////// Enumeration methods //////////
  175.         // Object for enumerating the list.
  176.         class MAPPOS
  177.         {
  178.             friend class TinyMap;
  179.             typedef List<pair_type>::POSITION LISTPOS;
  180.         public:
  181.             MAPPOS() 
  182.             {
  183.             }
  184.             bool operator==(const MAPPOS &p) const
  185.             {
  186.                 return pos == p.pos;
  187.             }
  188.             bool operator!=(const MAPPOS &p) const
  189.             {
  190.                 return pos != p.pos;
  191.             }
  192.         private:
  193.             LISTPOS pos;
  194.             MAPPOS(LISTPOS p) : pos(p) 
  195.             {
  196.             }
  197.         };
  198.         MAPPOS FrontPosition()
  199.         {
  200.             return MAPPOS( List<pair_type>::FrontPosition() );
  201.         }
  202.         MAPPOS EndPosition() const
  203.         {
  204.             return MAPPOS( List<pair_type>::EndPosition() );
  205.         }
  206.         HRESULT GetValue(MAPPOS vals, Value *ppItem)
  207.         {  
  208.             HRESULT hr = S_OK;
  209.             pair_type pair;
  210.             hr = List<pair_type>::GetItemPos(vals.pos, &pair);
  211.             if (SUCCEEDED(hr))
  212.             {
  213.                 *ppItem = pair.value;
  214.             }
  215.             return hr;
  216.         }
  217.         HRESULT GetKey(MAPPOS vals, Key *ppItem)
  218.         {  
  219.             HRESULT hr = S_OK;
  220.             pair_type pair;
  221.             hr = List<pair_type>::GetItemPos(vals.pos, &pair);
  222.             if (SUCCEEDED(hr))
  223.             {
  224.                 *ppItem = pair.key;
  225.             }
  226.             return hr;
  227.         }
  228.         MAPPOS Next(const MAPPOS vals)
  229.         {
  230.             return MAPPOS( List<pair_type>::Next( vals.pos ) );
  231.         }
  232.     };
  233. } // namespace MediaFoundationSamples