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.

995 lines
27 KiB

  1. /*++
  2. Copyright (C) 1996-1999 Microsoft Corporation
  3. Module Name:
  4. DUMBNODE.H
  5. Abstract:
  6. WBEM Evaluation Tree
  7. History:
  8. --*/
  9. template<class TPropType>
  10. CFullCompareNode<TPropType>::CFullCompareNode(
  11. const CFullCompareNode<TPropType>& Other,
  12. BOOL bChildren)
  13. : CPropertyNode(Other, FALSE), // copy without children
  14. m_pRightMost(NULL)
  15. {
  16. if(bChildren)
  17. {
  18. // Need to copy the children. Iterate over our test point array
  19. // =============================================================
  20. for(TConstTestPointIterator it = Other.m_aTestPoints.Begin();
  21. it != Other.m_aTestPoints.End(); it++)
  22. {
  23. CTestPoint<TPropType> NewPoint;
  24. NewPoint.m_Test = it->m_Test;
  25. // Make copies of the child branches
  26. // =================================
  27. NewPoint.m_pLeftOf = CEvalNode::CloneNode(it->m_pLeftOf);
  28. NewPoint.m_pAt = CEvalNode::CloneNode(it->m_pAt);
  29. // Add the test point to the array
  30. // ===============================
  31. m_aTestPoints.Append(NewPoint);
  32. }
  33. // Copy right-most
  34. // ===============
  35. m_pRightMost = CEvalNode::CloneNode(Other.m_pRightMost);
  36. }
  37. }
  38. template<class TPropType>
  39. HRESULT CFullCompareNode<TPropType>::SetTest(VARIANT& v)
  40. {
  41. try
  42. {
  43. CTokenValue Value;
  44. if(!Value.SetVariant(v))
  45. return WBEM_E_OUT_OF_MEMORY;
  46. m_aTestPoints.Begin()->m_Test = Value;
  47. return WBEM_S_NO_ERROR;
  48. }
  49. catch(CX_MemoryException)
  50. {
  51. return WBEM_E_OUT_OF_MEMORY;
  52. }
  53. }
  54. template<class TPropType>
  55. CFullCompareNode<TPropType>::~CFullCompareNode()
  56. {
  57. delete m_pRightMost;
  58. }
  59. template<class TPropType>
  60. HRESULT CFullCompareNode<TPropType>::InsertMatching(
  61. TTestPointIterator it,
  62. TTestPointIterator it2, TTestPointIterator& itLast,
  63. int nOp, CContextMetaData* pNamespace,
  64. CImplicationList& Implications, bool bDeleteArg2)
  65. {
  66. //=====================================================================
  67. // 'it' points to the node in 'this' that has the same value as the one
  68. // 'it2' points to in pArg2. 'itLast' points to the last unhandled node
  69. // in 'this' (looking left from 'it').
  70. //=====================================================================
  71. CEvalNode* pNew;
  72. HRESULT hres;
  73. // Merge our at-values
  74. // ===================
  75. hres = CEvalTree::Combine(it->m_pAt, it2->m_pAt, nOp, pNamespace,
  76. Implications, true, bDeleteArg2, &pNew);
  77. if(FAILED(hres))
  78. return hres;
  79. if(bDeleteArg2)
  80. it2->m_pAt = NULL;
  81. it->m_pAt = pNew;
  82. // Merge our left-ofs
  83. // ==================
  84. hres = CEvalTree::Combine(it->m_pLeftOf, it2->m_pLeftOf, nOp, pNamespace,
  85. Implications, true, bDeleteArg2, &pNew);
  86. if(FAILED(hres))
  87. return hres;
  88. if(bDeleteArg2)
  89. it2->m_pLeftOf = NULL;
  90. it->m_pLeftOf = pNew;
  91. //
  92. // At this point, we need to merge the LeftOf of it2 with all the branches
  93. // in this that are between the current insertion point and the previous
  94. // insertion point. However, we do not need to do this if it2's LeftOf node
  95. // is a noop for this operation (e.g. TRUE for an AND)
  96. //
  97. if(it != itLast && !CEvalNode::IsNoop(it2->m_pLeftOf, nOp))
  98. {
  99. hres = CombineWithBranchesToLeft(it, itLast, it2->m_pLeftOf, nOp,
  100. pNamespace, Implications);
  101. if(FAILED(hres))
  102. return hres;
  103. }
  104. // Move first unhandled iterator to the node beyond itLast
  105. // =======================================================
  106. itLast = it;
  107. itLast++;
  108. return WBEM_S_NO_ERROR;
  109. }
  110. template<class TPropType>
  111. HRESULT CFullCompareNode<TPropType>::InsertLess(
  112. TTestPointIterator it,
  113. TTestPointIterator it2, TTestPointIterator& itLast,
  114. int nOp, CContextMetaData* pNamespace,
  115. CImplicationList& Implications, bool bDeleteArg2)
  116. {
  117. //
  118. // 'it' points to the node in 'this' that has a slightly larger value than
  119. // the one 'it2' points to in pArg2. 'itLast' points to the last unhandled
  120. // node in 'this' (looking left from 'it').
  121. //
  122. HRESULT hres;
  123. // Check if 'it' is point to the end of the list --- in that case it's
  124. // "left-of" is actually right-most
  125. // ===================================================================
  126. CEvalNode* pItLeft = NULL;
  127. if(it == m_aTestPoints.End())
  128. pItLeft = m_pRightMost;
  129. else
  130. pItLeft = it->m_pLeftOf;
  131. // First of all, we need to insert the node at it2 into 'this' list, just
  132. // before 'it'.
  133. // ======================================================================
  134. CTestPoint<TPropType> NewNode = *it2;
  135. // It's at branch is the combination of our left and arg2 at
  136. // =========================================================
  137. hres = CEvalTree::Combine(pItLeft, it2->m_pAt, nOp, pNamespace,
  138. Implications, false, bDeleteArg2, &NewNode.m_pAt);
  139. if(FAILED(hres))
  140. return hres;
  141. if(bDeleteArg2)
  142. it2->m_pAt = NULL;
  143. // It's left-of branch is the combination of our left and arg2 left
  144. // ================================================================
  145. // We can reuse it2->Left iff every node left of 'it' in 'this' has been
  146. // handled
  147. // =====================================================================
  148. bool bDeleteIt2Left = (bDeleteArg2 && (it == itLast));
  149. hres = CEvalTree::Combine(pItLeft, it2->m_pLeftOf, nOp, pNamespace,
  150. Implications, false, bDeleteIt2Left, &NewNode.m_pLeftOf);
  151. if(FAILED(hres))
  152. return hres;
  153. if(bDeleteIt2Left)
  154. it2->m_pLeftOf = NULL;
  155. // IMPORTANT: Once we insert the new node, all the iterators into 'this'
  156. // will be invalidated --- that includes it and itLast. So, we need to do
  157. // out left-walk before we actually insert.
  158. // ===================================================
  159. //
  160. // At this point, we need to merge the LeftOf of it2 with all the branches
  161. // in this that are between the current insertion point and the previous
  162. // insertion point. However, we do not need to do this if it2's LeftOf node
  163. // is a noop for this operation (e.g. TRUE for an AND)
  164. //
  165. if(it != itLast && !CEvalNode::IsNoop(it2->m_pLeftOf, nOp))
  166. {
  167. //
  168. // Note to self: bDeleteIt2Left could not have been true, so
  169. // it2->m_pLeftOf could not have been deleted. We are OK here
  170. //
  171. hres = CombineWithBranchesToLeft(it, itLast, it2->m_pLeftOf, nOp,
  172. pNamespace, Implications);
  173. if(FAILED(hres))
  174. return hres;
  175. }
  176. // Now we can actually insert
  177. // ==========================
  178. TTestPointIterator itNew = m_aTestPoints.Insert(it, NewNode);
  179. // Move first unhandled iterator to the node just right of insertion
  180. // =================================================================
  181. itLast = itNew;
  182. itLast++;
  183. return WBEM_S_NO_ERROR;
  184. }
  185. template<class TPropType>
  186. HRESULT CFullCompareNode<TPropType>::CombineWithBranchesToLeft(
  187. TTestPointIterator itWalk, TTestPointIterator itLast,
  188. CEvalNode* pArg2,
  189. int nOp, CContextMetaData* pNamespace,
  190. CImplicationList& Implications)
  191. {
  192. HRESULT hres;
  193. CEvalNode* pNew = NULL;
  194. // Walk left until we reach the first unhandled node
  195. // =================================================
  196. do
  197. {
  198. if(itWalk == m_aTestPoints.Begin())
  199. break;
  200. itWalk--;
  201. // Merge at-value
  202. // ==============
  203. hres = CEvalTree::Combine(itWalk->m_pAt, pArg2, nOp,
  204. pNamespace, Implications, true, false, &pNew);
  205. if(FAILED(hres))
  206. return hres;
  207. itWalk->m_pAt = pNew;
  208. // Merge left-ofs
  209. // ==============
  210. hres = CEvalTree::Combine(itWalk->m_pLeftOf, pArg2, nOp,
  211. pNamespace, Implications, true, false, &pNew);
  212. if(FAILED(hres))
  213. return hres;
  214. itWalk->m_pLeftOf = pNew;
  215. }
  216. while(itWalk != itLast);
  217. return WBEM_S_NO_ERROR;
  218. }
  219. template<class TPropType>
  220. HRESULT CFullCompareNode<TPropType>::CombineBranchesWith(
  221. CBranchingNode* pRawArg2, int nOp, CContextMetaData* pNamespace,
  222. CImplicationList& Implications,
  223. bool bDeleteThis, bool bDeleteArg2, CEvalNode** ppRes)
  224. {
  225. HRESULT hres;
  226. CFullCompareNode<TPropType>* pArg2 = (CFullCompareNode<TPropType>*)pRawArg2;
  227. *ppRes = NULL;
  228. // Check which one is larger
  229. // =========================
  230. if(m_aTestPoints.GetSize() < pArg2->m_aTestPoints.GetSize())
  231. {
  232. return pArg2->CombineBranchesWith(this, FlipEvalOp(nOp), pNamespace,
  233. Implications, bDeleteArg2, bDeleteThis, ppRes);
  234. }
  235. if(!bDeleteThis)
  236. {
  237. // Damn. Clone.
  238. // ============
  239. return ((CFullCompareNode<TPropType>*)Clone())->CombineBranchesWith(
  240. pRawArg2, nOp, pNamespace, Implications, true, // reuse clone!
  241. bDeleteArg2, ppRes);
  242. }
  243. CEvalNode* pNew = NULL;
  244. TTestPointIterator itLast = m_aTestPoints.Begin();
  245. //
  246. // itLast points to the left-most location in our list of test points that
  247. // we have not considered yet --- it is guaranteed that any further
  248. // insertions from the second list will occur after this point
  249. //
  250. //
  251. // it2, on the other hand, iterates simply over the second list of test
  252. // points, inserting each one into the combined list one by one
  253. //
  254. for(TTestPointIterator it2 = pArg2->m_aTestPoints.Begin();
  255. it2 != pArg2->m_aTestPoints.End(); it2++)
  256. {
  257. //
  258. // First, we search for the location in our list of test points of the
  259. // insertion point for the value of it2. bMatch is set to true if the
  260. // same test point exists, and false if it does not and the returned
  261. // iterator points to the element to the right of the insertion point.
  262. //
  263. TTestPointIterator it;
  264. bool bMatch = m_aTestPoints.Find(it2->m_Test, &it);
  265. if(bMatch)
  266. {
  267. hres = InsertMatching(it, it2, itLast, nOp, pNamespace,
  268. Implications, bDeleteArg2);
  269. }
  270. else
  271. {
  272. hres = InsertLess(it, it2, itLast, nOp, pNamespace,
  273. Implications, bDeleteArg2);
  274. // invalidates 'it'!
  275. }
  276. if(FAILED(hres))
  277. return hres;
  278. }
  279. //
  280. // At this point, we need to merge the RightMost of arg2 with all the
  281. // branches in this that come after the last insertion point.
  282. // However, we do not need to do this if arg2's RightMost node
  283. // is a noop for this operation (e.g. TRUE for an AND)
  284. //
  285. if(itLast != m_aTestPoints.End() &&
  286. !CEvalNode::IsNoop(pArg2->m_pRightMost, nOp))
  287. {
  288. hres = CombineWithBranchesToLeft(m_aTestPoints.End(), itLast,
  289. pArg2->m_pRightMost, nOp, pNamespace, Implications);
  290. if(FAILED(hres))
  291. return hres;
  292. }
  293. hres = CEvalTree::Combine(m_pRightMost, pArg2->m_pRightMost, nOp,
  294. pNamespace, Implications, true, bDeleteArg2,
  295. &pNew);
  296. if(FAILED(hres))
  297. return hres;
  298. m_pRightMost = pNew;
  299. if(bDeleteArg2)
  300. pArg2->m_pRightMost = NULL;
  301. // Merge the nulls
  302. // ===============
  303. CEvalTree::Combine(m_pNullBranch, pArg2->m_pNullBranch, nOp,
  304. pNamespace, Implications, true, bDeleteArg2,
  305. &pNew);
  306. m_pNullBranch = pNew;
  307. // Reset them in deleted versions
  308. // ==============================
  309. if(bDeleteArg2)
  310. pArg2->m_pNullBranch = NULL;
  311. // Delete what needs deleting
  312. // ==========================
  313. if(bDeleteArg2)
  314. delete pArg2;
  315. *ppRes = this;
  316. return WBEM_S_NO_ERROR;
  317. }
  318. template<class TPropType>
  319. HRESULT CFullCompareNode<TPropType>::CombineInOrderWith(CEvalNode* pArg2,
  320. int nOp, CContextMetaData* pNamespace,
  321. CImplicationList& OrigImplications,
  322. bool bDeleteThis, bool bDeleteArg2,
  323. CEvalNode** ppRes)
  324. {
  325. HRESULT hres;
  326. *ppRes = Clone();
  327. if(*ppRes == NULL)
  328. return WBEM_E_OUT_OF_MEMORY;
  329. CFullCompareNode<TPropType>* pNew = (CFullCompareNode<TPropType>*)*ppRes;
  330. try
  331. {
  332. CImplicationList Implications(OrigImplications);
  333. hres = pNew->AdjustCompile(pNamespace, Implications);
  334. if(FAILED(hres))
  335. return hres;
  336. CEvalNode* pNewBranch = NULL;
  337. for(TTestPointIterator it = pNew->m_aTestPoints.Begin();
  338. it != pNew->m_aTestPoints.End(); it++)
  339. {
  340. // Combine our At-branch with pArg2
  341. // ================================
  342. hres = CEvalTree::Combine(it->m_pAt, pArg2, nOp, pNamespace,
  343. Implications, true, false, &pNewBranch);
  344. if(FAILED(hres))
  345. {
  346. delete pNew;
  347. return hres;
  348. }
  349. it->m_pAt = pNewBranch;
  350. // Now do the same for our left-of branch
  351. // ======================================
  352. hres = CEvalTree::Combine(it->m_pLeftOf, pArg2, nOp, pNamespace,
  353. Implications, true, false, &pNewBranch);
  354. if(FAILED(hres))
  355. {
  356. delete pNew;
  357. return hres;
  358. }
  359. it->m_pLeftOf = pNewBranch;
  360. }
  361. hres = CEvalTree::Combine(pNew->m_pRightMost, pArg2, nOp, pNamespace,
  362. Implications, true, false, &pNewBranch);
  363. if(FAILED(hres))
  364. {
  365. delete pNew;
  366. return hres;
  367. }
  368. pNew->m_pRightMost = pNewBranch;
  369. hres = CEvalTree::Combine(pNew->m_pNullBranch, pArg2, nOp, pNamespace,
  370. Implications, true, false, &pNewBranch);
  371. if(FAILED(hres))
  372. {
  373. delete pNew;
  374. return hres;
  375. }
  376. pNew->m_pNullBranch = pNewBranch;
  377. if(bDeleteThis)
  378. delete this;
  379. if(bDeleteArg2)
  380. delete pArg2;
  381. return WBEM_S_NO_ERROR;
  382. }
  383. catch(CX_MemoryException)
  384. {
  385. return WBEM_E_OUT_OF_MEMORY;
  386. }
  387. }
  388. template<class TPropType>
  389. int CFullCompareNode<TPropType>::SubCompare(CEvalNode* pRawOther)
  390. {
  391. CFullCompareNode<TPropType>* pOther =
  392. (CFullCompareNode<TPropType>*)pRawOther;
  393. // Compare handles
  394. // ===============
  395. int nCompare;
  396. nCompare = m_lPropHandle - pOther->m_lPropHandle;
  397. if(nCompare)
  398. return nCompare;
  399. // Compare array sizes
  400. // ===================
  401. nCompare = m_aTestPoints.GetSize() - pOther->m_aTestPoints.GetSize();
  402. if(nCompare)
  403. return nCompare;
  404. // Compare all points
  405. // ==================
  406. TTestPointIterator it;
  407. TTestPointIterator itOther;
  408. for(it = m_aTestPoints.Begin(), itOther = pOther->m_aTestPoints.Begin();
  409. it != m_aTestPoints.End(); it++, itOther++)
  410. {
  411. if(it->m_Test < itOther->m_Test)
  412. return -1;
  413. else if(it->m_Test > itOther->m_Test)
  414. return 1;
  415. }
  416. // Compare all branches
  417. // ====================
  418. for(it = m_aTestPoints.Begin(), itOther = pOther->m_aTestPoints.Begin();
  419. it != m_aTestPoints.End(); it++, itOther++)
  420. {
  421. nCompare = CEvalTree::Compare(it->m_pLeftOf, itOther->m_pLeftOf);
  422. if(nCompare)
  423. return nCompare;
  424. nCompare = CEvalTree::Compare(it->m_pAt, itOther->m_pAt);
  425. if(nCompare)
  426. return nCompare;
  427. }
  428. return 0;
  429. }
  430. template<class TPropType>
  431. HRESULT CFullCompareNode<TPropType>::OptimizeSelf()
  432. {
  433. TTestPointIterator it = m_aTestPoints.Begin();
  434. while(it != m_aTestPoints.End())
  435. {
  436. TTestPointIterator itPrev = it;
  437. it++;
  438. CEvalNode** ppLeft = &itPrev->m_pLeftOf;
  439. CEvalNode** ppMiddle = &itPrev->m_pAt;
  440. CEvalNode** ppRight = it != m_aTestPoints.End() ?
  441. &it->m_pLeftOf : &m_pRightMost;
  442. //
  443. // compare all three test point nodes. If all the same then we
  444. // can optimize the test point out. Also, two nodes are treated
  445. // the same if at least one of them is the invalid node.
  446. //
  447. if ( !CEvalNode::IsInvalid( *ppLeft ) )
  448. {
  449. if ( !CEvalNode::IsInvalid( *ppMiddle ) )
  450. {
  451. if( CEvalTree::Compare( *ppLeft, *ppMiddle ) != 0 )
  452. {
  453. continue;
  454. }
  455. }
  456. else
  457. {
  458. ppMiddle = ppLeft;
  459. }
  460. }
  461. if ( !CEvalNode::IsInvalid( *ppMiddle ) )
  462. {
  463. if ( !CEvalNode::IsInvalid( *ppRight ) )
  464. {
  465. if( CEvalTree::Compare( *ppMiddle, *ppRight ) != 0 )
  466. {
  467. continue;
  468. }
  469. }
  470. //
  471. // we're going to optimize the test point out, but first
  472. // make sure to set rightmost to point to the middle branch.
  473. // Make sure to unhook appropriate pointers before removing
  474. // the test node, since it owns the memory for them.
  475. //
  476. delete *ppRight;
  477. *ppRight = *ppMiddle;
  478. *ppMiddle = NULL;
  479. }
  480. //
  481. // optimize the test point out.
  482. //
  483. it = m_aTestPoints.Remove( itPrev );
  484. }
  485. return S_OK;
  486. }
  487. template<class TPropType>
  488. DWORD CFullCompareNode<TPropType>::ApplyPredicate(CLeafPredicate* pPred)
  489. {
  490. DWORD dwRes;
  491. for(TTestPointIterator it = m_aTestPoints.Begin();
  492. it != m_aTestPoints.End(); it++)
  493. {
  494. if (it->m_pLeftOf)
  495. {
  496. dwRes = it->m_pLeftOf->ApplyPredicate(pPred);
  497. if(dwRes & WBEM_DISPOSITION_FLAG_DELETE)
  498. {
  499. delete it->m_pLeftOf;
  500. it->m_pLeftOf = NULL;
  501. }
  502. else if ( dwRes & WBEM_DISPOSITION_FLAG_INVALIDATE )
  503. {
  504. delete it->m_pLeftOf;
  505. it->m_pLeftOf = CValueNode::GetStandardInvalid();
  506. }
  507. }
  508. if (it->m_pAt)
  509. {
  510. dwRes = it->m_pAt->ApplyPredicate(pPred);
  511. if(dwRes & WBEM_DISPOSITION_FLAG_DELETE)
  512. {
  513. delete it->m_pAt;
  514. it->m_pAt = NULL;
  515. }
  516. else if ( dwRes & WBEM_DISPOSITION_FLAG_INVALIDATE )
  517. {
  518. delete it->m_pAt;
  519. it->m_pAt = CValueNode::GetStandardInvalid();
  520. }
  521. }
  522. }
  523. if (m_pRightMost)
  524. {
  525. dwRes = m_pRightMost->ApplyPredicate(pPred);
  526. if(dwRes & WBEM_DISPOSITION_FLAG_DELETE)
  527. {
  528. delete m_pRightMost;
  529. m_pRightMost = NULL;
  530. }
  531. else if ( dwRes & WBEM_DISPOSITION_FLAG_INVALIDATE )
  532. {
  533. delete m_pRightMost;
  534. m_pRightMost = CValueNode::GetStandardInvalid();
  535. }
  536. }
  537. return CBranchingNode::ApplyPredicate(pPred);
  538. }
  539. template<class TPropType>
  540. HRESULT CFullCompareNode<TPropType>::Optimize(CContextMetaData* pNamespace,
  541. CEvalNode** ppNew)
  542. {
  543. CEvalNode* pNew = NULL;
  544. HRESULT hres;
  545. // Optimize all branches
  546. // =====================
  547. for(TTestPointIterator it = m_aTestPoints.Begin();
  548. it != m_aTestPoints.End(); it++)
  549. {
  550. if (it->m_pLeftOf)
  551. {
  552. hres = it->m_pLeftOf->Optimize(pNamespace, &pNew);
  553. if(FAILED(hres))
  554. return hres;
  555. if(pNew != it->m_pLeftOf)
  556. {
  557. delete it->m_pLeftOf;
  558. it->m_pLeftOf = pNew;
  559. }
  560. }
  561. if (it->m_pAt)
  562. {
  563. hres = it->m_pAt->Optimize(pNamespace, &pNew);
  564. if(FAILED(hres))
  565. return hres;
  566. if(pNew != it->m_pAt)
  567. {
  568. delete it->m_pAt;
  569. it->m_pAt = pNew;
  570. }
  571. }
  572. }
  573. if (m_pRightMost)
  574. {
  575. hres = m_pRightMost->Optimize(pNamespace, &pNew);
  576. if(FAILED(hres))
  577. return hres;
  578. if(pNew != m_pRightMost)
  579. {
  580. delete m_pRightMost;
  581. m_pRightMost = pNew;
  582. }
  583. }
  584. if (m_pNullBranch)
  585. {
  586. hres = m_pNullBranch->Optimize(pNamespace, &pNew);
  587. if(FAILED(hres))
  588. return hres;
  589. if(pNew != m_pNullBranch)
  590. {
  591. delete m_pNullBranch;
  592. m_pNullBranch = pNew;
  593. }
  594. }
  595. // Optimize ourselves
  596. // ==================
  597. hres = OptimizeSelf();
  598. if(FAILED(hres))
  599. return hres;
  600. *ppNew = this;
  601. //
  602. // Check if this node has become superflous
  603. //
  604. if( m_aTestPoints.GetSize() == 0 )
  605. {
  606. if ( !CEvalNode::IsInvalid( m_pRightMost ) )
  607. {
  608. if ( !CEvalNode::IsInvalid( m_pNullBranch ) )
  609. {
  610. if ( CEvalTree::Compare(m_pNullBranch, m_pRightMost) == 0 )
  611. {
  612. //
  613. // both the null and rightmost are the same. Optimize
  614. // this node out and return the rightmost branch.
  615. //
  616. *ppNew = m_pRightMost;
  617. //
  618. // Untie m_pRightMost (so it is not deleted when we are)
  619. //
  620. m_pRightMost = NULL;
  621. }
  622. }
  623. else if ( m_pRightMost == NULL )
  624. {
  625. //
  626. // the right branch is false and the null branch is invalid.
  627. // Optimize this node to false.
  628. //
  629. *ppNew = NULL;
  630. }
  631. }
  632. else if ( m_pNullBranch == NULL )
  633. {
  634. //
  635. // the null branch is false and the rightmost is invalid.
  636. // Optimize this node to false.
  637. //
  638. *ppNew = NULL;
  639. }
  640. else if ( CEvalNode::IsInvalid( m_pNullBranch ) )
  641. {
  642. //
  643. // both are invalid, but we can't invalidate the whole node
  644. // because we're not sure what we optimized out in the test
  645. // points, so just optimize this node to false.
  646. //
  647. *ppNew = NULL;
  648. }
  649. }
  650. return S_OK;
  651. }
  652. template<class TPropType>
  653. HRESULT CFullCompareNode<TPropType>::SetNullTest(int nOperator)
  654. {
  655. if(nOperator == QL1_OPERATOR_EQUALS)
  656. {
  657. m_pRightMost = CValueNode::GetStandardFalse();
  658. CEvalNode* pNode = CValueNode::GetStandardTrue();
  659. if(pNode == NULL)
  660. return WBEM_E_OUT_OF_MEMORY;
  661. SetNullBranch(pNode);
  662. }
  663. else if(nOperator == QL1_OPERATOR_NOTEQUALS)
  664. {
  665. m_pRightMost = CValueNode::GetStandardTrue();
  666. if(m_pRightMost == NULL)
  667. return WBEM_E_OUT_OF_MEMORY;
  668. SetNullBranch(CValueNode::GetStandardFalse());
  669. }
  670. else
  671. return WBEM_E_INVALID_QUERY;
  672. return WBEM_S_NO_ERROR;
  673. }
  674. template<class TPropType>
  675. HRESULT CFullCompareNode<TPropType>::SetOperator(int nOperator)
  676. {
  677. HRESULT hr = WBEM_S_NO_ERROR;
  678. #define GET_STD_TRUE CValueNode::GetStandardTrue()
  679. #define GET_STD_FALSE CValueNode::GetStandardFalse()
  680. #define SET_TRUE(NODE) { \
  681. NODE = GET_STD_TRUE; \
  682. if(NODE == NULL) { \
  683. hr = WBEM_E_OUT_OF_MEMORY; \
  684. break; } }
  685. #define SET_FALSE(NODE) {NODE = GET_STD_FALSE;}
  686. CTestPoint<TPropType> NewNode;
  687. switch(nOperator)
  688. {
  689. case QL1_OPERATOR_EQUALS:
  690. SET_FALSE(NewNode.m_pLeftOf);
  691. SET_TRUE(NewNode.m_pAt);
  692. SET_FALSE(m_pRightMost);
  693. break;
  694. case QL1_OPERATOR_NOTEQUALS:
  695. SET_TRUE(NewNode.m_pLeftOf);
  696. SET_FALSE(NewNode.m_pAt);
  697. SET_TRUE(m_pRightMost);
  698. break;
  699. case QL1_OPERATOR_LESS:
  700. SET_TRUE(NewNode.m_pLeftOf);
  701. SET_FALSE(NewNode.m_pAt);
  702. SET_FALSE(m_pRightMost);
  703. break;
  704. case QL1_OPERATOR_GREATER:
  705. SET_FALSE(NewNode.m_pLeftOf);
  706. SET_FALSE(NewNode.m_pAt);
  707. SET_TRUE(m_pRightMost);
  708. break;
  709. case QL1_OPERATOR_LESSOREQUALS:
  710. SET_TRUE(NewNode.m_pLeftOf);
  711. SET_TRUE(NewNode.m_pAt);
  712. SET_FALSE(m_pRightMost);
  713. break;
  714. case QL1_OPERATOR_GREATEROREQUALS:
  715. SET_FALSE(NewNode.m_pLeftOf);
  716. SET_TRUE(NewNode.m_pAt);
  717. SET_TRUE(m_pRightMost);
  718. break;
  719. default:
  720. hr = WBEM_E_CRITICAL_ERROR;
  721. }
  722. if ( SUCCEEDED(hr) )
  723. {
  724. m_aTestPoints.Append(NewNode);
  725. }
  726. else
  727. {
  728. NewNode.Destruct();
  729. }
  730. return hr;
  731. }
  732. //******************************************************************************
  733. //******************************************************************************
  734. // SCALAR PROPERTY NODE
  735. //******************************************************************************
  736. //******************************************************************************
  737. template<class TPropType>
  738. HRESULT CScalarPropNode<TPropType>::Evaluate(CObjectInfo& ObjInfo,
  739. INTERNAL CEvalNode** ppNext)
  740. {
  741. HRESULT hres;
  742. _IWmiObject* pObj;
  743. hres = GetContainerObject(ObjInfo, &pObj);
  744. if(FAILED(hres)) return hres;
  745. // Get the property from the object
  746. // ================================
  747. long lRead;
  748. TPropType Value;
  749. hres = pObj->ReadPropertyValue(m_lPropHandle, sizeof(TPropType),
  750. &lRead, (BYTE*)&Value);
  751. if( S_OK != hres )
  752. {
  753. if(hres == WBEM_S_FALSE)
  754. {
  755. *ppNext = m_pNullBranch;
  756. return WBEM_S_NO_ERROR;
  757. }
  758. else
  759. {
  760. return hres;
  761. }
  762. }
  763. // Search for the value
  764. // ====================
  765. TTestPointIterator it;
  766. bool bMatch = m_aTestPoints.Find(Value, &it);
  767. if(bMatch)
  768. *ppNext = it->m_pAt;
  769. else if(it == m_aTestPoints.End())
  770. *ppNext = m_pRightMost;
  771. else
  772. *ppNext = it->m_pLeftOf;
  773. return WBEM_S_NO_ERROR;
  774. }
  775. template<class TPropType>
  776. void CScalarPropNode<TPropType>::Dump(FILE* f, int nOffset)
  777. {
  778. CBranchingNode::Dump(f, nOffset);
  779. PrintOffset(f, nOffset);
  780. fprintf(f, "LastPropName = (0x%x), size=%d\n",
  781. m_lPropHandle, sizeof(TPropType));
  782. TConstTestPointIterator it;
  783. for(it = m_aTestPoints.Begin();
  784. it != m_aTestPoints.End(); it++)
  785. {
  786. PrintOffset(f, nOffset);
  787. if (it != m_aTestPoints.Begin())
  788. {
  789. TConstTestPointIterator itPrev(it);
  790. itPrev--;
  791. fprintf(f, "%d < ", (int)(itPrev->m_Test));
  792. }
  793. fprintf(f, "X < %d\n", (int)(it->m_Test));
  794. DumpNode(f, nOffset+1, it->m_pLeftOf);
  795. PrintOffset(f, nOffset);
  796. fprintf(f, "X = %d\n", (int)(it->m_Test));
  797. DumpNode(f, nOffset+1, it->m_pAt);
  798. }
  799. PrintOffset(f, nOffset);
  800. if (it != m_aTestPoints.Begin())
  801. {
  802. TConstTestPointIterator itPrev(it);
  803. itPrev--;
  804. fprintf(f, "X > %d\n", (int)(itPrev->m_Test));
  805. }
  806. else
  807. fprintf(f, "ANY\n");
  808. DumpNode(f, nOffset+1, m_pRightMost);
  809. PrintOffset(f, nOffset);
  810. fprintf(f, "NULL->\n");
  811. DumpNode(f, nOffset+1, m_pNullBranch);
  812. }