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.

600 lines
12 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows/NT **/
  3. /** Copyright(c) Microsoft Corporation, 1995 - 1999 **/
  4. /**********************************************************************/
  5. /*
  6. FILE HISTORY:
  7. */
  8. #define OEMRESOURCE
  9. #include "stdafx.h"
  10. #include <stdlib.h>
  11. #include <memory.h>
  12. #include <ctype.h>
  13. #include "objplus.h"
  14. #ifdef _DEBUG
  15. #undef THIS_FILE
  16. static char BASED_CODE THIS_FILE[] = __FILE__;
  17. #endif
  18. CObjHelper :: CObjHelper ()
  19. : m_ctor_err( 0 ),
  20. m_api_err( 0 ),
  21. m_b_dirty( FALSE ),
  22. m_time_created( ::GetCurrentTime() )
  23. {
  24. }
  25. void CObjHelper :: ReportError ( LONG errInConstruction )
  26. {
  27. Trace1("CObjectPlus construction failure, error = %d", errInConstruction);
  28. m_ctor_err = errInConstruction ;
  29. }
  30. LONG CObjHelper :: SetApiErr ( LONG errApi )
  31. {
  32. return m_api_err = errApi ;
  33. }
  34. void CObjHelper :: AssertValid () const
  35. {
  36. ASSERT( QueryError() == 0 ) ;
  37. }
  38. BOOL CObjHelper :: IsValid () const
  39. {
  40. return QueryError() == 0 ;
  41. }
  42. DWORD CObjHelper :: QueryAge () const
  43. {
  44. DWORD dwTime = ::GetCurrentTime(),
  45. dwDiff ;
  46. if ( dwTime < m_time_created )
  47. {
  48. dwDiff = dwTime + (((DWORD) -1) - (m_time_created - 1)) ;
  49. }
  50. else
  51. {
  52. dwDiff = dwTime - m_time_created ;
  53. }
  54. return dwDiff ;
  55. }
  56. // Constructor of extended object
  57. CObjectPlus :: CObjectPlus ()
  58. {
  59. }
  60. // Compare one object with another: default implementation
  61. // orders objects by creation time. Return -1, 0 or 1.
  62. int CObjectPlus :: Compare ( const CObjectPlus * pob ) const
  63. {
  64. return QueryCreationTime() < pob->QueryCreationTime()
  65. ? -1
  66. : QueryCreationTime() != pob->QueryCreationTime() ;
  67. }
  68. CObListIter :: CObListIter ( const CObOwnedList & obList )
  69. : m_obList( obList )
  70. {
  71. Reset() ;
  72. }
  73. void CObListIter :: Reset ()
  74. {
  75. m_pos = m_obList.GetCount() ? m_obList.GetHeadPosition() : NULL ;
  76. }
  77. CObject * CObListIter :: Next ()
  78. {
  79. return m_pos == NULL
  80. ? NULL
  81. : m_obList.GetNext( m_pos ) ;
  82. }
  83. //
  84. // Subclass of CObList whose default behavior is to destroy
  85. // its contents during its own destruction
  86. //
  87. CObOwnedList :: CObOwnedList ( int nBlockSize )
  88. : CObList( nBlockSize ),
  89. m_b_owned( TRUE )
  90. {
  91. }
  92. CObOwnedList :: ~ CObOwnedList ()
  93. {
  94. RemoveAll() ;
  95. }
  96. void CObOwnedList :: RemoveAll ()
  97. {
  98. if ( m_b_owned )
  99. {
  100. //
  101. // Remove and discard all the objects
  102. //
  103. while ( ! IsEmpty() )
  104. {
  105. CObject * pob = RemoveHead() ;
  106. delete pob ;
  107. }
  108. }
  109. else
  110. {
  111. // Just remove the object pointers
  112. CObList::RemoveAll() ;
  113. }
  114. }
  115. CObject * CObOwnedList :: Index ( int index )
  116. {
  117. CObListIter oli( *this ) ;
  118. CObject * pob ;
  119. for ( int i = 0 ; (pob = oli.Next()) && i++ < index ; ) ;
  120. return pob ;
  121. }
  122. CObject * CObOwnedList :: RemoveIndex ( int index )
  123. {
  124. POSITION pos ;
  125. CObListIter oli( *this ) ;
  126. int i ;
  127. CObject * pob ;
  128. for ( i = 0, pos = oli.QueryPosition() ;
  129. (pob = oli.Next()) && i < index ;
  130. i++, pos = oli.QueryPosition() ) ;
  131. if ( pob && i == index )
  132. {
  133. RemoveAt( pos ) ;
  134. }
  135. else
  136. {
  137. pob = NULL ;
  138. }
  139. return pob ;
  140. }
  141. // Remove the first (and hopefully only) occurrence of an object
  142. // pointer from this list.
  143. BOOL CObOwnedList :: Remove ( CObject * pob )
  144. {
  145. POSITION pos = Find( pob ) ;
  146. if ( pos == NULL )
  147. return FALSE ;
  148. RemoveAt( pos ) ;
  149. return TRUE ;
  150. }
  151. // Set all elements to dirty or clean. Return TRUE if
  152. // any element was dirty.
  153. BOOL CObOwnedList :: SetAll ( BOOL bDirty )
  154. {
  155. int cDirtyItems = 0 ;
  156. CObListIter oli( *this ) ;
  157. CObjectPlus * pob ;
  158. while ( pob = (CObjectPlus *) oli.Next() )
  159. {
  160. cDirtyItems += pob->IsDirty() ;
  161. pob->SetDirty( bDirty ) ;
  162. }
  163. SetDirty( bDirty );
  164. return cDirtyItems > 0 ;
  165. }
  166. int CObOwnedList :: FindElement ( CObject * pobSought ) const
  167. {
  168. CObListIter oli( *this ) ;
  169. CObject * pob ;
  170. for ( int i = 0 ;
  171. (pob = oli.Next()) && pob != pobSought ;
  172. i++ ) ;
  173. return pob ? i : -1 ;
  174. }
  175. // Override of CObList::AddTail() to control exception handling.
  176. // Returns NULL if addition fails.
  177. POSITION CObOwnedList :: AddTail (
  178. CObjectPlus * pobj,
  179. BOOL bThrowException )
  180. {
  181. POSITION pos = NULL ;
  182. // Catch only memory exceptions.
  183. TRY
  184. {
  185. pos = CObList::AddTail( pobj ) ;
  186. }
  187. CATCH( CMemoryException, e )
  188. {
  189. pos = NULL ;
  190. }
  191. END_CATCH
  192. if ( pos == NULL && bThrowException )
  193. {
  194. // CObList::AddTail() threw an exception. Echo it.
  195. AfxThrowMemoryException() ;
  196. }
  197. return pos ;
  198. }
  199. typedef struct
  200. {
  201. CObjectPlus * pObj ; // Pointer to object to be sorted
  202. CObjectPlus::PCOBJPLUS_ORDER_FUNC pFunc ; // Pointer to ordering function
  203. } CBOWNEDLIST_SORT_HELPER ;
  204. // This static member function is used to quick sort an array of structures
  205. // as declared above. Each element contains the object pointer and a
  206. // pointer to the object's member function to be invoked for comparison.
  207. //int CDECL CObOwnedList :: SortHelper (
  208. int _cdecl CObOwnedList :: SortHelper (
  209. const void * pa,
  210. const void * pb
  211. )
  212. {
  213. CBOWNEDLIST_SORT_HELPER
  214. * pHelp1 = (CBOWNEDLIST_SORT_HELPER *) pa,
  215. * pHelp2 = (CBOWNEDLIST_SORT_HELPER *) pb ;
  216. return (pHelp1->pObj->*pHelp1->pFunc)( pHelp2->pObj ) ;
  217. }
  218. // Sort the list by recreating it entirely.
  219. LONG CObOwnedList :: Sort ( CObjectPlus::PCOBJPLUS_ORDER_FUNC pOrderFunc )
  220. {
  221. LONG err = 0 ;
  222. int cItems = (int)GetCount() ;
  223. if ( cItems < 2 )
  224. return NO_ERROR ;
  225. CObListIter obli( *this ) ;
  226. CObjectPlus * pObNext ;
  227. BOOL bOwned = SetOwnership( FALSE ) ;
  228. int i ;
  229. CBOWNEDLIST_SORT_HELPER * paSortHelpers = NULL ;
  230. CATCH_MEM_EXCEPTION
  231. {
  232. // Allocate the helper array
  233. paSortHelpers = new CBOWNEDLIST_SORT_HELPER[ cItems ] ;
  234. /// Fill the helper array.
  235. for ( i = 0 ; pObNext = (CObjectPlus *) obli.Next() ; i++ )
  236. {
  237. paSortHelpers[i].pFunc = pOrderFunc ;
  238. paSortHelpers[i].pObj = pObNext ;
  239. }
  240. // Release all object pointer references. Note that we
  241. // forced "owned" to FALSE above.
  242. RemoveAll() ;
  243. ASSERT( GetCount() == 0 ) ;
  244. // Sort the helper array
  245. ::qsort( (void *) paSortHelpers,
  246. cItems,
  247. sizeof paSortHelpers[0],
  248. SortHelper ) ;
  249. // Refill the list from the helper array.
  250. for ( i = 0 ; i < cItems ; i++ )
  251. {
  252. AddTail( paSortHelpers[i].pObj ) ;
  253. }
  254. ASSERT( GetCount() == cItems ) ;
  255. }
  256. END_MEM_EXCEPTION(err)
  257. // Delete the working array
  258. delete [] paSortHelpers ;
  259. // Restore the object ownership state
  260. SetOwnership( bOwned ) ;
  261. return err ;
  262. }
  263. //
  264. // Subclass of CObArray whose default behavior is to destroy
  265. // its contents during its own destruction
  266. //
  267. CObOwnedArray :: CObOwnedArray ()
  268. : CObArray(),
  269. m_b_owned( TRUE )
  270. {
  271. }
  272. CObOwnedArray :: ~ CObOwnedArray ()
  273. {
  274. RemoveAll() ;
  275. }
  276. void CObOwnedArray :: RemoveAll ()
  277. {
  278. if ( m_b_owned )
  279. {
  280. int i, nElements;
  281. nElements = (int)GetSize();
  282. for (i = 0; i < nElements; ++i)
  283. {
  284. delete (CObject *)GetAt(i) ;
  285. }
  286. }
  287. //
  288. // Just remove the object pointers
  289. //
  290. CObArray::RemoveAll() ;
  291. }
  292. void
  293. CObOwnedArray :: RemoveAt (
  294. int nIndex,
  295. int nCount
  296. )
  297. {
  298. for (int i = 0; i < nCount; ++i)
  299. {
  300. delete (CObject *)GetAt(nIndex) ;
  301. }
  302. CObArray::RemoveAt(nIndex, nCount);
  303. }
  304. //
  305. // Set all elements to dirty or clean. Return TRUE if
  306. // any element was dirty.
  307. //
  308. BOOL
  309. CObOwnedArray :: SetAll (
  310. BOOL bDirty
  311. )
  312. {
  313. int cDirtyItems = 0 ;
  314. CObjectPlus * pob ;
  315. int i;
  316. int nElements = (int)GetSize();
  317. for (i = 0; i < nElements; ++i)
  318. {
  319. pob = (CObjectPlus *)GetAt(i);
  320. cDirtyItems += pob->IsDirty() ;
  321. pob->SetDirty( bDirty ) ;
  322. }
  323. SetDirty( bDirty );
  324. return cDirtyItems > 0 ;
  325. }
  326. int
  327. CObOwnedArray :: FindElement (
  328. CObject * pobSought
  329. ) const
  330. {
  331. CObject * pob ;
  332. int i;
  333. int nElements = (int)GetSize();
  334. for ( i = 0, pob = NULL; i < nElements && pob != pobSought; ++i)
  335. {
  336. pob = (CObject *)GetAt(i);
  337. }
  338. return i < nElements ? i : -1 ;
  339. }
  340. void
  341. CObOwnedArray :: Swap(
  342. int nIndx1,
  343. int nIndx2
  344. )
  345. {
  346. CObject * pTmp = GetAt(nIndx1);
  347. SetAt(nIndx1, GetAt(nIndx2));
  348. SetAt(nIndx2, pTmp);
  349. }
  350. //
  351. // This sort is pretty slow. Why?
  352. //
  353. void
  354. CObOwnedArray :: QuickSort(
  355. int nLow,
  356. int nHigh,
  357. CObjectPlus::PCOBJPLUS_ORDER_FUNC pOrderFunc
  358. )
  359. {
  360. int nUp, nDown;
  361. CObjectPlus * pBreak;
  362. if (nLow < nHigh)
  363. {
  364. if((nHigh - nLow) == 1)
  365. {
  366. if (((CObjectPlus *)GetAt(nLow)->*pOrderFunc)((CObjectPlus *)GetAt(nHigh)) > 0)
  367. {
  368. Swap(nLow, nHigh);
  369. }
  370. }
  371. else
  372. {
  373. pBreak = (CObjectPlus *)GetAt(nHigh);
  374. do
  375. {
  376. nUp = nLow;
  377. nDown = nHigh;
  378. while(nUp < nDown && ((CObjectPlus *)GetAt(nUp)->*pOrderFunc)(pBreak) <= 0)
  379. {
  380. ++nUp;
  381. }
  382. while(nDown > nUp && ((CObjectPlus *)GetAt(nDown)->*pOrderFunc)(pBreak) >= 0)
  383. {
  384. --nDown;
  385. }
  386. if (nUp < nDown)
  387. {
  388. Swap(nUp, nDown);
  389. }
  390. } while (nUp < nDown);
  391. Swap(nUp, nHigh);
  392. if ((nUp - nLow) < (nHigh - nUp) )
  393. {
  394. QuickSort(nLow, nUp - 1, pOrderFunc);
  395. QuickSort(nUp + 1, nHigh, pOrderFunc);
  396. }
  397. else
  398. {
  399. QuickSort(nUp + 1, nHigh, pOrderFunc);
  400. QuickSort(nLow, nUp - 1, pOrderFunc);
  401. }
  402. }
  403. }
  404. }
  405. /*
  406. LONG
  407. CObOwnedArray :: Sort (
  408. CObjectPlus::PCOBJPLUS_ORDER_FUNC pOrderFunc
  409. )
  410. {
  411. LONG err = 0 ;
  412. int cItems = GetSize() ;
  413. if ( cItems < 2 )
  414. {
  415. return NO_ERROR ;
  416. }
  417. QuickSort(0, GetUpperBound(), pOrderFunc);
  418. return 0;
  419. }
  420. */
  421. typedef struct
  422. {
  423. CObjectPlus * pObj ; // Pointer to object to be sorted
  424. CObjectPlus::PCOBJPLUS_ORDER_FUNC pFunc ; // Pointer to ordering function
  425. } CBOWNEDARRAY_SORT_HELPER ;
  426. // This static member function is used to quick sort an array of structures
  427. // as declared above. Each element contains the object pointer and a
  428. // pointer to the object's member function to be invoked for comparison.
  429. //int CDECL CObOwnedArray :: SortHelper (
  430. int _cdecl CObOwnedArray :: SortHelper (
  431. const void * pa,
  432. const void * pb
  433. )
  434. {
  435. CBOWNEDARRAY_SORT_HELPER
  436. * pHelp1 = (CBOWNEDARRAY_SORT_HELPER *) pa,
  437. * pHelp2 = (CBOWNEDARRAY_SORT_HELPER *) pb ;
  438. return (pHelp1->pObj->*pHelp1->pFunc)( pHelp2->pObj ) ;
  439. }
  440. // Sort the list by recreating it entirely.
  441. LONG
  442. CObOwnedArray :: Sort (
  443. CObjectPlus::PCOBJPLUS_ORDER_FUNC pOrderFunc
  444. )
  445. {
  446. LONG err = 0 ;
  447. int cItems = (int)GetSize() ;
  448. if ( cItems < 2 )
  449. {
  450. return NO_ERROR ;
  451. }
  452. CObjectPlus * pObNext ;
  453. BOOL bOwned = SetOwnership( FALSE ) ;
  454. int i ;
  455. CBOWNEDARRAY_SORT_HELPER * paSortHelpers = NULL ;
  456. CATCH_MEM_EXCEPTION
  457. {
  458. // Allocate the helper array
  459. paSortHelpers = new CBOWNEDARRAY_SORT_HELPER[ cItems ] ;
  460. /// Fill the helper array.
  461. for ( i = 0 ; i < cItems ; ++i )
  462. {
  463. pObNext = (CObjectPlus *) GetAt(i);
  464. paSortHelpers[i].pFunc = pOrderFunc ;
  465. paSortHelpers[i].pObj = pObNext ;
  466. }
  467. // Release all object pointer references. Note that we
  468. // forced "owned" to FALSE above.
  469. RemoveAll() ;
  470. ASSERT( GetSize() == 0 ) ;
  471. // Sort the helper array
  472. ::qsort( (void *) paSortHelpers,
  473. cItems,
  474. sizeof paSortHelpers[0],
  475. SortHelper ) ;
  476. // Refill the list from the helper array.
  477. for ( i = 0 ; i < cItems ; i++ )
  478. {
  479. Add( paSortHelpers[i].pObj ) ;
  480. }
  481. ASSERT( GetSize() == cItems ) ;
  482. }
  483. END_MEM_EXCEPTION(err)
  484. // Delete the working array
  485. delete [] paSortHelpers ;
  486. // Restore the object ownership state
  487. SetOwnership( bOwned ) ;
  488. return err ;
  489. }