Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

179 lines
4.2 KiB

  1. /*===================================================================
  2. Microsoft Denali
  3. Microsoft Confidential.
  4. Copyright 1996 Microsoft Corporation. All Rights Reserved.
  5. Component: Hash table for Script Manager
  6. File: SMHash.cpp
  7. Owner: AndrewS
  8. This is the Link list and Hash table for use by the Script Manager only
  9. ===================================================================*/
  10. #include "denpre.h"
  11. #pragma hdrstop
  12. #include "memchk.h"
  13. /*===================================================================
  14. CSMHash::AddElem
  15. Adds a CLruLinkElem to the SM Hash table.
  16. User is responsible for allocating the Element to be added.
  17. Note: This is identical to the standard CHashTable::AddElem, except
  18. that it allows for elements with duplicate names
  19. Parameters:
  20. CLruLinkElem *pElem Object to be added
  21. Returns:
  22. Pointer to element added/found.
  23. ===================================================================*/
  24. CLruLinkElem *CSMHash::AddElem
  25. (
  26. CLruLinkElem *pElem
  27. )
  28. {
  29. AssertValid();
  30. if (m_rgpBuckets == NULL)
  31. {
  32. if (FAILED(AllocateBuckets()))
  33. return NULL;
  34. }
  35. if (pElem == NULL)
  36. return NULL;
  37. UINT iBucket = m_pfnHash(pElem->m_pKey, pElem->m_cbKey) % m_cBuckets;
  38. CLruLinkElem * pT = static_cast<CLruLinkElem *>(m_rgpBuckets[iBucket]);
  39. while (pT)
  40. {
  41. if (pT->m_Info > 0)
  42. pT = static_cast<CLruLinkElem *>(pT->m_pNext);
  43. else
  44. break;
  45. }
  46. if (pT)
  47. {
  48. // There are other elements in bucket
  49. pT = static_cast<CLruLinkElem *>(m_rgpBuckets[iBucket]);
  50. m_rgpBuckets[iBucket] = pElem;
  51. pElem->m_Info = pT->m_Info + 1;
  52. pElem->m_pNext = pT;
  53. pElem->m_pPrev = pT->m_pPrev;
  54. pT->m_pPrev = pElem;
  55. if (pElem->m_pPrev == NULL)
  56. m_pHead = pElem;
  57. else
  58. pElem->m_pPrev->m_pNext = pElem;
  59. }
  60. else
  61. {
  62. // This is the first element in the bucket
  63. m_rgpBuckets[iBucket] = pElem;
  64. pElem->m_pPrev = NULL;
  65. pElem->m_pNext = m_pHead;
  66. pElem->m_Info = 0;
  67. if (m_pHead)
  68. m_pHead->m_pPrev = pElem;
  69. else
  70. m_pTail = pElem;
  71. m_pHead = pElem;
  72. }
  73. m_Count++;
  74. pElem->PrependTo(m_lruHead);
  75. AssertValid();
  76. return pElem;
  77. }
  78. /*===================================================================
  79. CSMHash::FindElem
  80. Finds a script engine element in the hash table based on the name
  81. and language type.
  82. Parameters:
  83. void * pKey - the key to look for
  84. int cbKey - length of the key to look for
  85. PROGLANG_ID proglang_id - program language name
  86. DWORD dwInstanceID - instance ID to find
  87. BOOL fCheckLoaded - if true, only return engines flagged as "loaded"
  88. Returns:
  89. Pointer to CLruLinkElem if found, otherwise NULL.
  90. ===================================================================*/
  91. CLruLinkElem * CSMHash::FindElem
  92. (
  93. const void *pKey,
  94. int cbKey,
  95. PROGLANG_ID proglang_id,
  96. DWORD dwInstanceID,
  97. BOOL fCheckLoaded
  98. )
  99. {
  100. AssertValid();
  101. if (m_rgpBuckets == NULL || pKey == NULL)
  102. return NULL;
  103. UINT iBucket = m_pfnHash(static_cast<const BYTE *>(pKey), cbKey) % m_cBuckets;
  104. CLruLinkElem * pT = static_cast<CLruLinkElem *>(m_rgpBuckets[iBucket]);
  105. CLruLinkElem * pRet = NULL;
  106. /*
  107. * We have the right bucket based on the hashed name.
  108. * Search through the bucket chain looking for elements whose name
  109. * is correct (multiple names can hash to the same bucket), and
  110. * whose language is the one we want, and (optionally) skip
  111. * elements that are not fully "loaded"
  112. *
  113. * Note: This all relys on intimate knowlege of the format of an ActiveScriptEngine.
  114. * these elements better be ASE's.
  115. */
  116. while (pT && pRet == NULL)
  117. {
  118. if (FIsEqual(pT->m_pKey, pT->m_cbKey, pKey, cbKey))
  119. {
  120. CASEElem *pASEElem = static_cast<CASEElem *>(pT);
  121. Assert(pASEElem != NULL);
  122. CActiveScriptEngine *pASE = pASEElem->PASE();
  123. Assert(pASE != NULL);
  124. // Element has the right name. Is it really the one we want?
  125. if (proglang_id != pASE->ProgLang_Id())
  126. goto LNext;
  127. if (dwInstanceID != pASE->DWInstanceID())
  128. goto LNext;
  129. if (fCheckLoaded && !pASE->FFullyLoaded())
  130. goto LNext;
  131. // Yup, its the right one!
  132. pRet = pT;
  133. break;
  134. }
  135. LNext:
  136. if (pT->m_Info > 0)
  137. pT = static_cast<CLruLinkElem *>(pT->m_pNext);
  138. else
  139. {
  140. // got to the last element in this bucket chain
  141. break;
  142. }
  143. }
  144. if (pRet)
  145. pRet->PrependTo(m_lruHead);
  146. AssertValid();
  147. return pRet;
  148. }