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.

779 lines
10 KiB

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