Leaked source code of windows server 2003
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.

2253 lines
54 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. All rights reserved.
  4. Module Name:
  5. spcompat.hxx
  6. Abstract:
  7. porting the spool library code into printui
  8. Author:
  9. Lazar Ivanov (LazarI) Jul-05-2000
  10. Revision History:
  11. --*/
  12. #ifndef _SPLLIB_HXX
  13. #define _SPLLIB_HXX
  14. #if DBG
  15. #define _INLINE
  16. #else
  17. #define _INLINE inline
  18. #endif
  19. ///////////////////////////////////////////////////
  20. // @@file@@ debug.hxx
  21. ///////////////////////////////////////////////////
  22. /********************************************************************
  23. C++ specific debug functionality.
  24. ********************************************************************/
  25. #ifdef __cplusplus
  26. #if DBG
  27. /********************************************************************
  28. Automatic status logging.
  29. Use TStatus instead of DWORD:
  30. DWORD dwStatus; -> TStatus Status;
  31. dwStatus = ERROR_SUCCESS -> Status DBGNOCHK = ERROR_SUCCESS;
  32. dwStatus = xxx; -> Status DBGCHK = xxx;
  33. if( dwStatus ){ -> if( Status != 0 ){
  34. Anytime Status is set, the DBGCHK macro must be added before
  35. the '=.'
  36. If the variable must be set to a failure value at compilte time
  37. and logging is therefore not needed, then the DBGNOCHK macro
  38. should be used.
  39. There are different parameters to instantiation. Alternate
  40. debug level can be specified, and also 3 "benign" errors that
  41. can be ignored.
  42. TStatus Status( DBG_ERROR, ERROR_ACCESS_DENIED, ERROR_FOO );
  43. ********************************************************************/
  44. #define DBGCHK .pSetInfo( MODULE_DEBUG, __LINE__, __FILE__, MODULE )
  45. #define DBGNOCHK .pNoChk()
  46. class TStatusBase {
  47. protected:
  48. DWORD _dwStatus;
  49. DWORD _dwStatusSafe1;
  50. DWORD _dwStatusSafe2;
  51. DWORD _dwStatusSafe3;
  52. UINT _uDbgLevel;
  53. UINT _uDbg;
  54. UINT _uLine;
  55. LPCSTR _pszFileA;
  56. LPCSTR _pszModuleA;
  57. public:
  58. TStatusBase(
  59. UINT uDbgLevel,
  60. DWORD dwStatusSafe1,
  61. DWORD dwStatusSafe2,
  62. DWORD dwStatusSafe3
  63. ) : _dwStatus( 0xdeacface ), _uDbgLevel( uDbgLevel ),
  64. _dwStatusSafe1( dwStatusSafe1 ), _dwStatusSafe2( dwStatusSafe2 ),
  65. _dwStatusSafe3( dwStatusSafe3 )
  66. { }
  67. TStatusBase&
  68. pSetInfo(
  69. UINT uDbg,
  70. UINT uLine,
  71. LPCSTR pszFileA,
  72. LPCSTR pszModuleA
  73. );
  74. TStatusBase&
  75. pNoChk(
  76. VOID
  77. );
  78. DWORD
  79. operator=(
  80. DWORD dwStatus
  81. );
  82. };
  83. class TStatus : public TStatusBase {
  84. private:
  85. //
  86. // Don't let clients use operator= without going through the
  87. // base class (i.e., using DBGCHK ).
  88. //
  89. // If you get an error trying to access private member function '=,'
  90. // you are trying to set the status without using the DBGCHK macro.
  91. //
  92. // This is needed to update the line and file, which must be done
  93. // at the macro level (not inline C++ function) since __LINE__ and
  94. // __FILE__ are handled by the preprocessor.
  95. //
  96. DWORD
  97. operator=(
  98. DWORD dwStatus
  99. );
  100. public:
  101. TStatus(
  102. UINT uDbgLevel = DBG_WARN,
  103. DWORD dwStatusSafe1 = (DWORD)-1,
  104. DWORD dwStatusSafe2 = (DWORD)-1,
  105. DWORD dwStatusSafe3 = (DWORD)-1
  106. ) : TStatusBase( uDbgLevel,
  107. dwStatusSafe1,
  108. dwStatusSafe2,
  109. dwStatusSafe3 )
  110. { }
  111. DWORD
  112. dwGetStatus(
  113. VOID
  114. );
  115. operator DWORD()
  116. {
  117. return dwGetStatus();
  118. }
  119. };
  120. /********************************************************************
  121. Same thing, but for HRESULT status.
  122. ********************************************************************/
  123. class TStatusHBase {
  124. protected:
  125. HRESULT _hrStatus;
  126. HRESULT _hrStatusSafe1;
  127. HRESULT _hrStatusSafe2;
  128. HRESULT _hrStatusSafe3;
  129. UINT _uDbgLevel;
  130. UINT _uDbg;
  131. UINT _uLine;
  132. LPCSTR _pszFileA;
  133. LPCSTR _pszModuleA;
  134. public:
  135. TStatusHBase(
  136. UINT uDbgLevel = DBG_WARN,
  137. HRESULT hrStatusSafe1 = S_FALSE,
  138. HRESULT hrStatusSafe2 = S_FALSE,
  139. HRESULT hrStatusSafe3 = S_FALSE
  140. ) : _hrStatus( 0xdeacface ), _uDbgLevel( uDbgLevel ),
  141. _hrStatusSafe1( hrStatusSafe1 ), _hrStatusSafe2( hrStatusSafe2 ),
  142. _hrStatusSafe3( hrStatusSafe3 )
  143. { }
  144. TStatusHBase&
  145. pSetInfo(
  146. UINT uDbg,
  147. UINT uLine,
  148. LPCSTR pszFileA,
  149. LPCSTR pszModuleA
  150. );
  151. TStatusHBase&
  152. pNoChk(
  153. VOID
  154. );
  155. HRESULT
  156. operator=(
  157. HRESULT hrStatus
  158. );
  159. };
  160. class TStatusH : public TStatusHBase {
  161. private:
  162. //
  163. // Don't let clients use operator= without going through the
  164. // base class (i.e., using DBGCHK ).
  165. //
  166. // If you get an error trying to access private member function '=,'
  167. // you are trying to set the status without using the DBGCHK macro.
  168. //
  169. // This is needed to update the line and file, which must be done
  170. // at the macro level (not inline C++ function) since __LINE__ and
  171. // __FILE__ are handled by the preprocessor.
  172. //
  173. HRESULT
  174. operator=(
  175. HRESULT hrStatus
  176. );
  177. public:
  178. TStatusH(
  179. UINT uDbgLevel = DBG_WARN,
  180. HRESULT hrStatusSafe1 = S_FALSE,
  181. HRESULT hrStatusSafe2 = S_FALSE,
  182. HRESULT hrStatusSafe3 = S_FALSE
  183. ) : TStatusHBase( uDbgLevel,
  184. hrStatusSafe1,
  185. hrStatusSafe2,
  186. hrStatusSafe3 )
  187. { }
  188. HRESULT
  189. hrGetStatus(
  190. VOID
  191. );
  192. operator HRESULT()
  193. {
  194. return hrGetStatus();
  195. }
  196. };
  197. /********************************************************************
  198. Same thing, but for BOOL status.
  199. ********************************************************************/
  200. class TStatusBBase {
  201. protected:
  202. BOOL _bStatus;
  203. DWORD _dwStatusSafe1;
  204. DWORD _dwStatusSafe2;
  205. DWORD _dwStatusSafe3;
  206. UINT _uDbgLevel;
  207. UINT _uDbg;
  208. UINT _uLine;
  209. LPCSTR _pszFileA;
  210. LPCSTR _pszModuleA;
  211. public:
  212. TStatusBBase(
  213. UINT uDbgLevel,
  214. DWORD dwStatusSafe1,
  215. DWORD dwStatusSafe2,
  216. DWORD dwStatusSafe3
  217. ) : _bStatus( 0xabababab ), _uDbgLevel( uDbgLevel ),
  218. _dwStatusSafe1( dwStatusSafe1 ), _dwStatusSafe2( dwStatusSafe2 ),
  219. _dwStatusSafe3( dwStatusSafe3 )
  220. { }
  221. TStatusBBase&
  222. pSetInfo(
  223. UINT uDbg,
  224. UINT uLine,
  225. LPCSTR pszFileA,
  226. LPCSTR pszModuleA
  227. );
  228. TStatusBBase&
  229. pNoChk(
  230. VOID
  231. );
  232. BOOL
  233. operator=(
  234. BOOL bStatus
  235. );
  236. };
  237. class TStatusB : public TStatusBBase {
  238. private:
  239. //
  240. // Don't let clients use operator= without going through the
  241. // base class (i.e., using DBGCHK ).
  242. //
  243. // If you get an error trying to access private member function '=,'
  244. // you are trying to set the status without using the DBGCHK macro.
  245. //
  246. // This is needed to update the line and file, which must be done
  247. // at the macro level (not inline C++ function) since __LINE__ and
  248. // __FILE__ are handled by the preprocessor.
  249. //
  250. BOOL
  251. operator=(
  252. BOOL bStatus
  253. );
  254. public:
  255. TStatusB(
  256. UINT uDbgLevel = DBG_WARN,
  257. DWORD dwStatusSafe1 = (DWORD)-1,
  258. DWORD dwStatusSafe2 = (DWORD)-1,
  259. DWORD dwStatusSafe3 = (DWORD)-1
  260. ) : TStatusBBase( uDbgLevel,
  261. dwStatusSafe1,
  262. dwStatusSafe2,
  263. dwStatusSafe3 )
  264. { }
  265. BOOL
  266. bGetStatus(
  267. VOID
  268. );
  269. operator BOOL()
  270. {
  271. return bGetStatus();
  272. }
  273. };
  274. #else
  275. #define DBGCHK
  276. #define DBGNOCHK
  277. class TStatus {
  278. private:
  279. DWORD _dwStatus;
  280. public:
  281. TStatus(
  282. UINT uDbgLevel = 0,
  283. DWORD dwStatusSafe1 = 0,
  284. DWORD dwStatusSafe2 = 0,
  285. DWORD dwStatusSafe3 = 0
  286. )
  287. { }
  288. DWORD
  289. operator=(
  290. DWORD dwStatus
  291. )
  292. {
  293. return _dwStatus = dwStatus;
  294. }
  295. operator DWORD()
  296. {
  297. return _dwStatus;
  298. }
  299. };
  300. class TStatusB {
  301. private:
  302. BOOL _bStatus;
  303. public:
  304. TStatusB(
  305. UINT uDbgLevel = 0,
  306. DWORD dwStatusSafe1 = 0,
  307. DWORD dwStatusSafe2 = 0,
  308. DWORD dwStatusSafe3 = 0
  309. )
  310. { }
  311. BOOL
  312. operator=(
  313. BOOL bStatus
  314. )
  315. {
  316. return _bStatus = bStatus;
  317. }
  318. operator BOOL()
  319. {
  320. return _bStatus;
  321. }
  322. };
  323. class TStatusH {
  324. private:
  325. HRESULT _hrStatus;
  326. public:
  327. TStatusH(
  328. UINT uDbgLevel = 0,
  329. HRESULT hrStatusSafe1 = 0,
  330. HRESULT hrStatusSafe2 = 0,
  331. HRESULT hrStatusSafe3 = 0
  332. )
  333. { }
  334. HRESULT
  335. operator=(
  336. HRESULT hrStatus
  337. )
  338. {
  339. return _hrStatus = hrStatus;
  340. }
  341. operator HRESULT()
  342. {
  343. return _hrStatus;
  344. }
  345. };
  346. #endif // #if DBG
  347. #endif // #ifdef __cplusplus
  348. ///////////////////////////////////////////////////
  349. // @@file@@ common.hxx
  350. ///////////////////////////////////////////////////
  351. //
  352. // This reverses a DWORD so that the bytes can be easily read
  353. // as characters ('prnt' can be read from debugger forward).
  354. //
  355. #define BYTE_SWAP_DWORD( val ) \
  356. ( (val & 0xff) << 24 | \
  357. (val & 0xff00) << 8 | \
  358. (val & 0xff0000) >> 8 | \
  359. (val & 0xff000000) >> 24 )
  360. #define COUNTOF(x) (sizeof(x)/sizeof(*x))
  361. #define BITCOUNTOF(x) (sizeof(x)*8)
  362. #define COUNT2BYTES(x) ((x)*sizeof(TCHAR))
  363. #define OFFSETOF(type, id) ((DWORD)(ULONG_PTR)(&(((type*)0)->id)))
  364. #define OFFSETOF_BASE(type, baseclass) ((DWORD)(ULONG_PTR)((baseclass*)((type*)0x10))-0x10)
  365. #define ERRORP(Status) (Status != ERROR_SUCCESS)
  366. #define SUCCESSP(Status) (Status == ERROR_SUCCESS)
  367. //
  368. // COUNT and COUNT BYTES
  369. //
  370. typedef UINT COUNT, *PCOUNT;
  371. typedef UINT COUNTB, *PCOUNTB;
  372. typedef DWORD STATUS;
  373. //
  374. // Conversion between PPM (Page per minute), LPM (Line per minute)
  375. // and CPS (Character per second)
  376. //
  377. #define CPS2PPM(x) ((x)/48)
  378. #define LPM2PPM(x) ((x)/48)
  379. //
  380. // C++ specific functionality.
  381. //
  382. #ifdef __cplusplus
  383. const DWORD kStrMax = MAX_PATH;
  384. #define SAFE_NEW
  385. #define DBG_SAFE_NEW
  386. #define SIGNATURE( sig ) \
  387. public: \
  388. class TSignature { \
  389. public: \
  390. DWORD _Signature; \
  391. TSignature() : _Signature( BYTE_SWAP_DWORD( sig )) { } \
  392. }; \
  393. TSignature _Signature; \
  394. \
  395. BOOL bSigCheck() const \
  396. { return _Signature._Signature == BYTE_SWAP_DWORD( sig ); } \
  397. private:
  398. #define ALWAYS_VALID \
  399. public: \
  400. BOOL bValid() const \
  401. { return TRUE; } \
  402. private:
  403. #define VAR(type,var) \
  404. inline type& var() \
  405. { return _##var; } \
  406. inline type const & var() const \
  407. { return _##var; } \
  408. type _##var
  409. #define SVAR(type,var) \
  410. static inline type& var() \
  411. { return _##var; } \
  412. static type _##var
  413. inline
  414. DWORD
  415. DWordAlign(
  416. DWORD dw
  417. )
  418. {
  419. return ((dw)+3)&~3;
  420. }
  421. inline
  422. PVOID
  423. DWordAlignDown(
  424. PVOID pv
  425. )
  426. {
  427. return (PVOID)((ULONG_PTR)pv&~3);
  428. }
  429. inline
  430. PVOID
  431. WordAlignDown(
  432. PVOID pv
  433. )
  434. {
  435. return (PVOID)((ULONG_PTR)pv&~1);
  436. }
  437. inline
  438. DWORD
  439. Align(
  440. DWORD dw
  441. )
  442. {
  443. return (dw+7)&~7;
  444. }
  445. #endif // __cplusplus
  446. ///////////////////////////////////////////////////
  447. // @@file@@ string.hxx
  448. ///////////////////////////////////////////////////
  449. class TString {
  450. SIGNATURE( 'strg' )
  451. SAFE_NEW
  452. public:
  453. //
  454. // For the default constructor, we initialize _pszString to a
  455. // global gszState[kValid] string. This allows them to work correctly,
  456. // but prevents the extra memory allocation.
  457. //
  458. // Note: if this class is extended (with reference counting
  459. // or "smart" reallocations), this strategy may break.
  460. //
  461. TString(
  462. VOID
  463. );
  464. TString(
  465. IN LPCTSTR psz
  466. );
  467. ~TString(
  468. VOID
  469. );
  470. TString(
  471. IN const TString &String
  472. );
  473. BOOL
  474. bEmpty(
  475. VOID
  476. ) const;
  477. BOOL
  478. bValid(
  479. VOID
  480. ) const;
  481. BOOL
  482. bUpdate(
  483. IN LPCTSTR pszNew
  484. );
  485. BOOL
  486. bLoadString(
  487. IN HINSTANCE hInst,
  488. IN UINT uID
  489. );
  490. UINT
  491. TString::
  492. uLen(
  493. VOID
  494. ) const;
  495. BOOL
  496. TString::
  497. bCat(
  498. IN LPCTSTR psz
  499. );
  500. BOOL
  501. TString::
  502. bLimitBuffer(
  503. IN UINT nMaxLength
  504. );
  505. BOOL
  506. TString::
  507. bDeleteChar(
  508. IN UINT nPos
  509. );
  510. BOOL
  511. TString::
  512. bReplaceAll(
  513. IN TCHAR chFrom,
  514. IN TCHAR chTo
  515. );
  516. VOID
  517. TString::
  518. vToUpper(
  519. VOID
  520. );
  521. VOID
  522. TString::
  523. vToLower(
  524. VOID
  525. );
  526. //
  527. // Caution: See function header for usage and side effects.
  528. //
  529. BOOL
  530. TString::
  531. bFormat(
  532. IN LPCTSTR pszFmt,
  533. IN ...
  534. );
  535. //
  536. // Caution: See function header for usage and side effects.
  537. //
  538. BOOL
  539. TString::
  540. bvFormat(
  541. IN LPCTSTR pszFmt,
  542. IN va_list avlist
  543. );
  544. //
  545. // Operator overloads.
  546. //
  547. operator LPCTSTR( VOID ) const
  548. { return _pszString; }
  549. friend INT operator==(const TString& String, LPCTSTR& psz)
  550. { return !lstrcmp(String._pszString, psz); }
  551. friend INT operator==(LPCTSTR& psz, const TString& String)
  552. { return !lstrcmp(psz, String._pszString); }
  553. friend INT operator==(const TString& String1, const TString& String2)
  554. { return !lstrcmp(String1._pszString, String2._pszString); }
  555. friend INT operator!=(const TString& String, LPCTSTR& psz)
  556. { return lstrcmp(String._pszString, psz) != 0; }
  557. friend INT operator!=(LPCTSTR& psz, const TString& String)
  558. { return lstrcmp(psz, String._pszString) != 0; }
  559. friend INT operator!=(const TString& String1, const TString& String2)
  560. { return lstrcmp(String1._pszString, String2._pszString) != 0; }
  561. protected:
  562. //
  563. // Not defined; used bUpdate since this forces clients to
  564. // check whether the assignment succeeded (it may fail due
  565. // to lack of memory, etc.).
  566. //
  567. TString& operator=( LPCTSTR psz );
  568. TString& operator=(const TString& String);
  569. private:
  570. enum StringStatus {
  571. kValid = 0,
  572. kInValid = 1,
  573. };
  574. enum {
  575. kStrIncrement = 256,
  576. kStrMaxFormatSize = 1024 * 100,
  577. };
  578. LPTSTR _pszString;
  579. static TCHAR gszNullState[2];
  580. LPTSTR
  581. TString::
  582. vsntprintf(
  583. IN LPCTSTR szFmt,
  584. IN va_list pArgs
  585. );
  586. VOID
  587. TString::
  588. vFree(
  589. IN LPTSTR pszString
  590. );
  591. };
  592. ///////////////////////////////////////////////////
  593. // @@file@@ state.hxx
  594. ///////////////////////////////////////////////////
  595. typedef DWORD STATEVAR;
  596. /********************************************************************
  597. State object (DWORD) for bitfields.
  598. ********************************************************************/
  599. class TState
  600. {
  601. SIGNATURE( 'stat' )
  602. ALWAYS_VALID
  603. SAFE_NEW
  604. public:
  605. #if DBG
  606. TState( VOID );
  607. TState( STATEVAR StateVar );
  608. ~TState( VOID );
  609. STATEVAR operator|=( STATEVAR StateVarOn );
  610. STATEVAR operator&=( STATEVAR StateVarMask );
  611. STATEVAR operator|=( INT iStateVarOn )
  612. { return operator|=( (STATEVAR)iStateVarOn ); }
  613. STATEVAR operator&=( INT iStateVarMask )
  614. { return operator&=( (STATEVAR)iStateVarMask ); }
  615. #else
  616. TState(VOID) : _StateVar(0)
  617. { }
  618. TState(STATEVAR StateVar) : _StateVar( StateVar )
  619. { }
  620. ~TState(VOID)
  621. { }
  622. STATEVAR operator|=( STATEVAR StateVarOn )
  623. { return _StateVar |= StateVarOn; }
  624. STATEVAR operator&=( STATEVAR StateVarMask )
  625. { return _StateVar &= StateVarMask; }
  626. STATEVAR operator|=( INT iStateVarOn )
  627. { return operator|=( (STATEVAR)iStateVarOn ); }
  628. STATEVAR operator&=( INT iStateVarMask )
  629. { return operator&=( (STATEVAR)iStateVarMask ); }
  630. #endif
  631. BOOL bBit( STATEVAR StateVarBit )
  632. { return _StateVar & StateVarBit ? TRUE : FALSE; }
  633. STATEVAR operator&( TState& State )
  634. { return _StateVar & State._StateVar; }
  635. STATEVAR operator=( STATEVAR StateVarNew )
  636. { return _StateVar = StateVarNew; }
  637. TState& operator=( const TState& StateNew )
  638. {
  639. _StateVar = StateNew._StateVar;
  640. return *this;
  641. }
  642. operator STATEVAR() const
  643. { return _StateVar; }
  644. private:
  645. STATEVAR _StateVar;
  646. #if DBG
  647. virtual BOOL bValidateState() const
  648. { return TRUE; }
  649. virtual BOOL bValidateSet(STATEVAR StateVarOn) const
  650. {
  651. UNREFERENCED_PARAMETER( StateVarOn );
  652. return TRUE;
  653. }
  654. virtual BOOL bValidateMask(STATEVAR StateVarMask) const
  655. {
  656. UNREFERENCED_PARAMETER( StateVarMask );
  657. return TRUE;
  658. }
  659. #endif
  660. };
  661. class VRef {
  662. SAFE_NEW
  663. public:
  664. virtual ~VRef()
  665. { }
  666. //
  667. // Virtuals that must be overwritten by the reference classes.
  668. //
  669. virtual VOID vIncRef() = 0;
  670. virtual LONG cDecRef() = 0;
  671. virtual VOID vDecRefDelete() = 0;
  672. protected:
  673. //
  674. // Clients of the reference class should override this class
  675. // to perform cleanup. Generally clients will implement vRefZeroed
  676. // to delete themselves.
  677. //
  678. virtual VOID vRefZeroed() = 0;
  679. };
  680. /************************************************************
  681. MRefCom: Refcount with interlocks
  682. ************************************************************/
  683. class MRefCom : public VRef {
  684. SIGNATURE( 'refc' )
  685. ALWAYS_VALID
  686. public:
  687. #if DBG
  688. MRefCom( VOID ) : _cRef( 0 )
  689. { }
  690. ~MRefCom( VOID )
  691. {
  692. SPLASSERT( !_cRef );
  693. }
  694. #else
  695. MRefCom( VOID ) : _cRef( 0 )
  696. { }
  697. #endif
  698. VOID vIncRef();
  699. LONG cDecRef();
  700. VOID vDecRefDelete();
  701. protected:
  702. //
  703. // Must be LONG, not REFCOUNT for Interlocked* apis.
  704. //
  705. VAR( LONG, cRef );
  706. virtual VOID vRefZeroed();
  707. };
  708. /************************************************************
  709. TRefLock: used to lock a VRef.
  710. ************************************************************/
  711. template<class T>
  712. class TRefLock {
  713. SIGNATURE( 'refl' )
  714. ALWAYS_VALID
  715. SAFE_NEW
  716. public:
  717. TRefLock(
  718. VOID
  719. ) : _pRef( NULL )
  720. { }
  721. TRefLock(
  722. T* pRef
  723. )
  724. {
  725. _pRef = pRef;
  726. _pRef->vIncRef( );
  727. }
  728. ~TRefLock( )
  729. {
  730. if( _pRef )
  731. _pRef->cDecRef( );
  732. }
  733. VOID vAcquire( T* pRef )
  734. {
  735. SPLASSERT( !_pRef );
  736. _pRef = pRef;
  737. _pRef->vIncRef( );
  738. }
  739. VOID vRelease( VOID )
  740. {
  741. SPLASSERT( _pRef );
  742. _pRef->cDecRef( );
  743. _pRef = NULL;
  744. }
  745. T*
  746. pGet(
  747. VOID
  748. ) const
  749. {
  750. return _pRef;
  751. }
  752. T*
  753. operator->(
  754. VOID
  755. ) const
  756. {
  757. return _pRef;
  758. }
  759. private:
  760. //
  761. // Copying and assignement not defined.
  762. //
  763. TRefLock( const TRefLock & );
  764. TRefLock & operator =(const TRefLock &);
  765. T *_pRef;
  766. };
  767. ///////////////////////////////////////////////////
  768. // @@file@@ splutil.hxx
  769. ///////////////////////////////////////////////////
  770. //
  771. // Double linked list. DLINK must be the same as DLINKBASE, except
  772. // with differnt constructors.
  773. //
  774. typedef struct DLINK {
  775. DLINK()
  776. { FLink = NULL; }
  777. DLINK* FLink;
  778. DLINK* BLink;
  779. } *PDLINK;
  780. typedef struct DLINKBASE {
  781. DLINKBASE()
  782. { FLink = BLink = (PDLINK)this; }
  783. DLINK* FLink;
  784. DLINK* BLink;
  785. } *PDLINKBASE;
  786. class TIter {
  787. public:
  788. PDLINK _pdlink;
  789. PDLINK _pdlBase;
  790. BOOL
  791. bValid()
  792. { return _pdlink != _pdlBase; }
  793. VOID
  794. vNext()
  795. { _pdlink = _pdlink->FLink; }
  796. VOID
  797. vPrev()
  798. { _pdlink = _pdlink->BLink; }
  799. operator PDLINK()
  800. { return _pdlink; }
  801. };
  802. /********************************************************************
  803. // Forward reference.
  804. class TLink;
  805. TBase has two linked lists of TLink.
  806. class TBase {
  807. DLINK_BASE( TLink, Link, Link );
  808. DLINK_BASE( TLink, Link2, Link2 );
  809. };
  810. class TLink {
  811. DLINK( TLink, Link );
  812. DLINK( TLink, Link2 );
  813. };
  814. //
  815. // Append pLink to the end of the Link2 list.
  816. //
  817. pBase->Link2_vAppend( pLink );
  818. //
  819. // Insert pLinkInsert right after pLinkMiddle.
  820. //
  821. pBase->Link_vInsert( pLinkMiddle, pLinkInsert );
  822. //
  823. // Get to the head.
  824. //
  825. pLinkHead = pBase->Link_pHead();
  826. //
  827. // To get to the next element in the list.
  828. //
  829. pLink = pLinkHead->Link_pNext();
  830. //
  831. // Remove an element from the list.
  832. //
  833. pLink->pLink_vDelinkSelf();
  834. //
  835. // Using the iter class.
  836. //
  837. TIter Iter;
  838. for( Link_vIterInit( Iter ), Iter.vNext(); Iter.bValid(); Iter.vNext( )){
  839. //
  840. // Use pLink.
  841. //
  842. vLinkOperation( pLink );
  843. }
  844. ********************************************************************/
  845. #define DLINK_BASE( type, name, linkname ) \
  846. VOID name##_vReset() \
  847. { pdl##name()->FLink = pdl##name()->BLink = pdl##name(); } \
  848. \
  849. PDLINK name##_pdlHead() const \
  850. { return pdl##name()->FLink; } \
  851. \
  852. PDLINK name##_pdlBase() const \
  853. { return pdl##name(); } \
  854. \
  855. type* name##_pHead( VOID ) const \
  856. { \
  857. return name##_bValid( name##_pdlHead() ) ? \
  858. (type*)((PBYTE)name##_pdlHead() - OFFSETOF( type, \
  859. _dl##linkname )) : \
  860. NULL; \
  861. } \
  862. \
  863. BOOL name##_bValid( PDLINK pdlink ) const \
  864. { return pdlink != pdl##name(); } \
  865. \
  866. VOID name##_vAdd( type* pType ) \
  867. { name##_vInsert( pdl##name(), pType->pdl##linkname( )); } \
  868. \
  869. VOID name##_vAppend( type* pType ) \
  870. { name##_vInsert( pdl##name()->BLink, pType->pdl##linkname( )); } \
  871. \
  872. VOID name##_vInsert( PDLINK pdlink1, type* pType2 ) \
  873. { name##_vInsert( pdlink1, pType2->pdl##linkname() ); } \
  874. \
  875. VOID name##_vInsert( PDLINK pdlink1, PDLINK pdlink2 ) \
  876. { \
  877. SPLASSERT( !pdlink2->FLink ); \
  878. pdlink1->FLink->BLink = pdlink2; \
  879. \
  880. pdlink2->BLink = pdlink1; \
  881. pdlink2->FLink = pdlink1->FLink; \
  882. \
  883. pdlink1->FLink = pdlink2; \
  884. } \
  885. \
  886. VOID name##_vInsertBefore( PDLINK pdlink1, type* pType2 ) \
  887. { name##_vInsertBefore( pdlink1, pType2->pdl##linkname() ); } \
  888. \
  889. VOID name##_vInsertBefore( PDLINK pdlink1, PDLINK pdlink2 ) \
  890. { \
  891. SPLASSERT( !pdlink2->FLink ); \
  892. pdlink1->BLink->FLink = pdlink2; \
  893. \
  894. pdlink2->FLink = pdlink1; \
  895. pdlink2->BLink = pdlink1->BLink; \
  896. \
  897. pdlink1->BLink = pdlink2; \
  898. } \
  899. \
  900. VOID name##_vDelink( type* pType ) \
  901. { name##_vDelink( pType->pdl##linkname( )); } \
  902. \
  903. VOID name##_vDelink( PDLINK pdlink ) \
  904. { \
  905. pdlink->FLink->BLink = pdlink->BLink; \
  906. pdlink->BLink->FLink = pdlink->FLink; \
  907. pdlink->FLink = NULL; \
  908. } \
  909. \
  910. type* name##_pFind( type* pType ) const \
  911. { \
  912. PDLINK pdlinkT; \
  913. PDLINK pdlink = pType->pdl##linkname(); \
  914. \
  915. for( pdlinkT = name##_pdlHead(); \
  916. name##_bValid( pdlinkT ); \
  917. pdlinkT = pdlinkT->FLink ){ \
  918. \
  919. if( pType->pdl##linkname() == pdlinkT ) \
  920. return (type*)((PBYTE)pdlink - OFFSETOF( type, \
  921. _dl##linkname )); \
  922. } \
  923. return NULL; \
  924. } \
  925. \
  926. PDLINK name##_pdlFind( PDLINK pdlink ) const \
  927. { \
  928. PDLINK pdlinkT; \
  929. for( pdlinkT = name##_pdlHead(); \
  930. name##_bValid( pdlinkT ); \
  931. pdlinkT = pdlinkT->FLink ){ \
  932. \
  933. if( pdlink == pdlinkT ) \
  934. return pdlink; \
  935. } \
  936. return NULL; \
  937. } \
  938. \
  939. PDLINK name##_pdlGetByIndex( UINT uIndex ) const \
  940. { \
  941. PDLINK pdlink; \
  942. for( pdlink = name##_pdlHead(); \
  943. uIndex; \
  944. uIndex--, pdlink = pdlink->FLink ){ \
  945. \
  946. SPLASSERT( name##_bValid( pdlink )); \
  947. } \
  948. return pdlink; \
  949. } \
  950. \
  951. type* name##_pGetByIndex( UINT uIndex ) const \
  952. { \
  953. PDLINK pdlink; \
  954. for( pdlink = name##_pdlHead(); \
  955. uIndex; \
  956. uIndex--, pdlink = pdlink->FLink ){ \
  957. \
  958. SPLASSERT( name##_bValid( pdlink )); \
  959. } \
  960. return name##_pConvert( pdlink ); \
  961. } \
  962. \
  963. static PDLINK name##_pdlNext( PDLINK pdlink ) \
  964. { return pdlink->FLink; } \
  965. \
  966. static type* name##_pConvert( PDLINK pdlink ) \
  967. { return (type*)( (PBYTE)pdlink - OFFSETOF( type, _dl##linkname )); } \
  968. \
  969. PDLINK pdl##name( VOID ) const \
  970. { return (PDLINK)&_dlb##name; } \
  971. \
  972. BOOL name##_bEmpty() const \
  973. { return pdl##name()->FLink == pdl##name(); } \
  974. \
  975. VOID name##_vIterInit( TIter& Iter ) const \
  976. { Iter._pdlBase = Iter._pdlink = (PDLINK)&_dlb##name; } \
  977. \
  978. DLINKBASE _dlb##name;
  979. \
  980. #define DLINK( type, name ) \
  981. PDLINK pdl##name() \
  982. { return &_dl##name; } \
  983. \
  984. VOID name##_vDelinkSelf( VOID ) \
  985. { \
  986. _dl##name.FLink->BLink = _dl##name.BLink; \
  987. _dl##name.BLink->FLink = _dl##name.FLink; \
  988. _dl##name.FLink = NULL; \
  989. } \
  990. \
  991. BOOL name##_bLinked() const \
  992. { return _dl##name.FLink != NULL; } \
  993. \
  994. PDLINK name##_pdlNext( VOID ) const \
  995. { return _dl##name.FLink; } \
  996. \
  997. PDLINK name##_pdlPrev( VOID ) const \
  998. { return _dl##name.BLink; } \
  999. \
  1000. type* name##_pNext( VOID ) const \
  1001. { return name##_pConvert( _dl##name.FLink ); } \
  1002. \
  1003. type* name##_pPrev( VOID ) const \
  1004. { return name##_pConvert( _dl##name.BLink ); } \
  1005. \
  1006. static type* name##_pConvert( PDLINK pdlink ) \
  1007. { return (type*)( (PBYTE)pdlink - OFFSETOF( type, _dl##name )); } \
  1008. \
  1009. DLINK _dl##name
  1010. //
  1011. // Generic MEntry class that allows objects to be stored on a list
  1012. // and searched by name.
  1013. //
  1014. class MEntry {
  1015. SIGNATURE( 'entr' )
  1016. public:
  1017. DLINK( MEntry, Entry );
  1018. TString _strName;
  1019. BOOL bValid()
  1020. {
  1021. return _strName.bValid();
  1022. }
  1023. static MEntry* pFindEntry( PDLINK pdlink, LPCTSTR pszName );
  1024. };
  1025. #define ENTRY_BASE( type, name ) \
  1026. friend MEntry; \
  1027. type* name##_pFindByName( LPCTSTR pszName ) const \
  1028. { \
  1029. MEntry* pEntry = MEntry::pFindEntry( name##_pdlBase(), pszName ); \
  1030. return pEntry ? (type*)pEntry : NULL; \
  1031. } \
  1032. static type* name##_pConvertEntry( PDLINK pdlink ) \
  1033. { \
  1034. return (type*)name##_pConvert( pdlink ); \
  1035. } \
  1036. DLINK_BASE( MEntry, name, Entry )
  1037. #define DELETE_ENTRY_LIST( type, name ) \
  1038. { \
  1039. PDLINK pdlink; \
  1040. type* pType; \
  1041. \
  1042. for( pdlink = name##_pdlHead(); name##_bValid( pdlink ); ){ \
  1043. \
  1044. pType = name##_pConvertEntry( pdlink ); \
  1045. pdlink = name##_pdlNext( pdlink ); \
  1046. \
  1047. pType->vDelete(); \
  1048. } \
  1049. }
  1050. ///////////////////////////////////////////////////
  1051. // @@file@@ threadm.hxx
  1052. ///////////////////////////////////////////////////
  1053. typedef PVOID PJOB;
  1054. class CCSLock;
  1055. class TThreadM
  1056. {
  1057. SIGNATURE( 'thdm' )
  1058. SAFE_NEW
  1059. private:
  1060. enum _States
  1061. {
  1062. kDestroyReq = 1,
  1063. kDestroyed = 2,
  1064. kPrivateCritSec = 4
  1065. } States;
  1066. /********************************************************************
  1067. Valid TMSTATUS states:
  1068. NULL -- Normal processing
  1069. DESTROY_REQ -- No new jobs, jobs possibly running
  1070. DESTROY_REQ, DESTROYED -- No new jobs, all jobs completed
  1071. ********************************************************************/
  1072. TState _State;
  1073. UINT _uIdleLife;
  1074. UINT _uMaxThreads;
  1075. UINT _uActiveThreads;
  1076. UINT _uRunNowThreads;
  1077. INT _iIdleThreads;
  1078. HANDLE _hTrigger;
  1079. CCSLock *_pCritSec;
  1080. LONG _lLocks;
  1081. DWORD
  1082. dwThreadProc(
  1083. VOID
  1084. );
  1085. static DWORD
  1086. xdwThreadProc(
  1087. PVOID pVoid
  1088. );
  1089. virtual PJOB
  1090. pThreadMJobNext(
  1091. VOID
  1092. ) = 0;
  1093. virtual VOID
  1094. vThreadMJobProcess(
  1095. PJOB pJob
  1096. ) = 0;
  1097. protected:
  1098. TThreadM(
  1099. UINT uMaxThreads,
  1100. UINT uIdleLife,
  1101. CCSLock* pCritSec
  1102. );
  1103. virtual
  1104. ~TThreadM(
  1105. VOID
  1106. );
  1107. BOOL
  1108. bValid(
  1109. VOID
  1110. ) const
  1111. {
  1112. return _hTrigger != NULL;
  1113. }
  1114. BOOL
  1115. bJobAdded(
  1116. BOOL bRunNow
  1117. );
  1118. VOID
  1119. vDelete(
  1120. VOID
  1121. );
  1122. LONG
  1123. Lock(
  1124. VOID
  1125. )
  1126. {
  1127. return InterlockedIncrement(&_lLocks);
  1128. }
  1129. LONG
  1130. Unlock(
  1131. VOID
  1132. )
  1133. {
  1134. LONG lLocks = InterlockedDecrement(&_lLocks);
  1135. if (0 == lLocks)
  1136. delete this;
  1137. return lLocks;
  1138. }
  1139. };
  1140. ///////////////////////////////////////////////////
  1141. // @@file@@ exec.hxx
  1142. ///////////////////////////////////////////////////
  1143. /********************************************************************
  1144. This module implements an asynchronous, pooled threads to
  1145. processes worker jobs.
  1146. class TJobUnit : public MExecWork {
  1147. ...
  1148. }
  1149. gpExec->bJobAdd( pJobUnit, USER_SPECIFIED_BITFIELD );
  1150. //
  1151. // When thread is available to process job,
  1152. // pJobUnit->svExecute( USER_SPECIFIED_BITFIELD, ... )
  1153. // will be called.
  1154. //
  1155. Declare a class Work derived from the mix-in MExecWork. When
  1156. work needs to be done on an instantiation of Work, it is queued
  1157. and immediately returned. A DWORD bitfield--4 high bits are
  1158. predefined--indicates the type of work needed.
  1159. This DWORD should be a bitfield, so if there are multiple
  1160. bJobAdd requests and all threads are busy, these DWORDs are
  1161. OR'd together.
  1162. That is,
  1163. bJobAdd( pJobUnit, 0x1 );
  1164. bJobAdd( pJobUnit, 0x2 );
  1165. bJobAdd( pJobUnit, 0x4 );
  1166. bJobAdd( pJobUnit, 0x8 );
  1167. We will call svExecute with 0xf.
  1168. Two threads will never operate on one job simultaneously. This
  1169. is guarenteed by this library.
  1170. The worker routine is defined by the virtual function stExecute().
  1171. ********************************************************************/
  1172. typedef enum _STATE_EXEC {
  1173. kExecUser = 0x08000000, // Here and below user may specify.
  1174. kExecRunNow = 0x10000000, // Ignore thread limit.
  1175. kExecExit = 0x20000000, // User requests the TExec exits.
  1176. kExecActive = 0x40000000, // Private: job is actively running.
  1177. kExecActiveReq = 0x80000000, // Private: job is queued.
  1178. kExecPrivate = kExecActive | kExecActiveReq,
  1179. kExecNoOutput = kExecPrivate | kExecRunNow
  1180. } STATE_EXEC;
  1181. class TExec;
  1182. class MExecWork {
  1183. friend TExec;
  1184. SIGNATURE( 'exwk' );
  1185. ALWAYS_VALID
  1186. SAFE_NEW
  1187. private:
  1188. DLINK( MExecWork, Work );
  1189. //
  1190. // Accessed by worker thread.
  1191. //
  1192. VAR( TState, State );
  1193. //
  1194. // StatePending is work that is pending (accumulated while the
  1195. // job is executing in a thread). The job at this stage is
  1196. // not in the queue.
  1197. //
  1198. VAR( TState, StatePending );
  1199. virtual
  1200. STATEVAR
  1201. svExecute(
  1202. STATEVAR StateVar
  1203. ) = 0;
  1204. virtual
  1205. VOID
  1206. vExecFailedAddJob(
  1207. VOID
  1208. ) = 0;
  1209. /********************************************************************
  1210. vExecExitComplete is called when a job completes and it is
  1211. pending deletion. This allows a client to allow all pending
  1212. work to complete before it deletes the object.
  1213. User adds job.
  1214. Job starts executing..,
  1215. User decides job should be deleted so adds EXEC_EXIT.
  1216. ... job finally completes.
  1217. Library calls vExecExitComplete on job
  1218. Client can now delete work object in vExecExitComplete call.
  1219. Note that only jobs that are currently executing are allowed
  1220. to complete. Jobs that are queued to work will exit immediately.
  1221. ********************************************************************/
  1222. virtual
  1223. VOID
  1224. vExecExitComplete(
  1225. VOID
  1226. ) = 0;
  1227. };
  1228. class TExec : public TThreadM {
  1229. SIGNATURE( 'exec' );
  1230. SAFE_NEW
  1231. public:
  1232. TExec( CCSLock* pCritSec );
  1233. //
  1234. // Clients should use vDelete, _not_ ~TExec.
  1235. //
  1236. ~TExec(
  1237. VOID
  1238. )
  1239. { }
  1240. VOID
  1241. vDelete(
  1242. VOID
  1243. )
  1244. {
  1245. TThreadM::vDelete();
  1246. }
  1247. BOOL
  1248. bValid(
  1249. VOID
  1250. ) const
  1251. {
  1252. return TThreadM::bValid();
  1253. }
  1254. BOOL
  1255. bJobAdd(
  1256. MExecWork* pExecWork,
  1257. STATEVAR StateVar
  1258. );
  1259. VOID
  1260. vJobDone(
  1261. MExecWork* pExecWork,
  1262. STATEVAR StateVar
  1263. );
  1264. STATEVAR
  1265. svClearPendingWork(
  1266. MExecWork* pExecWork
  1267. );
  1268. private:
  1269. DLINK_BASE( MExecWork, Work, Work );
  1270. CCSLock* _pCritSec;
  1271. //
  1272. // Virtual definitions for TThreadM.
  1273. //
  1274. PJOB
  1275. pThreadMJobNext(
  1276. VOID
  1277. );
  1278. VOID
  1279. vThreadMJobProcess(
  1280. PJOB pJob
  1281. );
  1282. BOOL
  1283. bJobAddWorker(
  1284. MExecWork* pExecWork
  1285. );
  1286. };
  1287. ///////////////////////////////////////////////////
  1288. // @@file@@ mem.hxx
  1289. ///////////////////////////////////////////////////
  1290. #define AllocMem(cb) malloc(cb)
  1291. #define FreeMem(ptr) free(ptr)
  1292. ///////////////////////////////////////////////////
  1293. // @@file@@ bitarray.hxx
  1294. ///////////////////////////////////////////////////
  1295. class TBitArray {
  1296. public:
  1297. typedef UINT Type;
  1298. enum {
  1299. kBitsInType = sizeof( Type ) * 8,
  1300. kBitsInTypeMask = 0xFFFFFFFF,
  1301. };
  1302. TBitArray(
  1303. IN UINT uBits = kBitsInType,
  1304. IN UINT uGrowSize = kBitsInType
  1305. );
  1306. TBitArray(
  1307. IN const TBitArray &rhs
  1308. );
  1309. const TBitArray &
  1310. operator=(
  1311. IN const TBitArray &rhs
  1312. );
  1313. ~TBitArray(
  1314. VOID
  1315. );
  1316. BOOL
  1317. bValid(
  1318. VOID
  1319. ) const;
  1320. BOOL
  1321. bToString( // Return string representation of bit array
  1322. IN TString &strBits
  1323. ) const;
  1324. BOOL
  1325. bRead(
  1326. IN UINT uBit // Range 0 to nBit - 1
  1327. ) const;
  1328. BOOL
  1329. bSet(
  1330. IN UINT uBit // Range 0 to nBit - 1
  1331. );
  1332. BOOL
  1333. bReset(
  1334. IN UINT uBit // Range 0 to nBit - 1
  1335. );
  1336. BOOL
  1337. bToggle(
  1338. IN UINT uBit // Range 0 to nBit - 1
  1339. );
  1340. BOOL
  1341. bAdd(
  1342. VOID // Add one bit to the array
  1343. );
  1344. UINT
  1345. uNumBits( // Return the total number of bits in the array
  1346. VOID
  1347. ) const;
  1348. VOID
  1349. vSetAll( // Set all the bits in the array
  1350. VOID
  1351. );
  1352. VOID
  1353. vResetAll( // Reset all the bits in the array
  1354. VOID
  1355. );
  1356. BOOL
  1357. bFindNextResetBit( // Locate first cleared bit in the array
  1358. IN UINT *puNextFreeBit
  1359. );
  1360. private:
  1361. BOOL
  1362. bClone( // Make a copy of the bit array
  1363. IN const TBitArray &rhs
  1364. );
  1365. BOOL
  1366. bGrow( // Expand the bit array by x number of bits
  1367. IN UINT uGrowSize
  1368. );
  1369. UINT
  1370. nBitsToType(
  1371. IN UINT uBits // Range 1 to nBit
  1372. ) const;
  1373. Type
  1374. BitToMask(
  1375. IN UINT uBit // Range 0 to nBit - 1
  1376. ) const;
  1377. UINT
  1378. BitToIndex(
  1379. IN UINT uBit // Range 0 to nBit - 1
  1380. ) const;
  1381. BOOL
  1382. bIsValidBit(
  1383. IN UINT uBit // Range 0 to nBit - 1
  1384. ) const;
  1385. UINT _nBits; // Number of currently allocated bits, Range 1 to n
  1386. Type *_pBits; // Pointer to array which contains the bits
  1387. UINT _uGrowSize; // Default number of bits to grow by
  1388. };
  1389. ///////////////////////////////////////////////////
  1390. // @@file@@ loadlib.hxx
  1391. ///////////////////////////////////////////////////
  1392. /********************************************************************
  1393. Helper class to load and release a DLL. Use the bValid for
  1394. library load validation.
  1395. ********************************************************************/
  1396. class TLibrary {
  1397. public:
  1398. TLibrary::
  1399. TLibrary(
  1400. IN LPCTSTR pszLibName
  1401. );
  1402. TLibrary::
  1403. ~TLibrary(
  1404. );
  1405. BOOL
  1406. TLibrary::
  1407. bValid(
  1408. VOID
  1409. ) const;
  1410. FARPROC
  1411. TLibrary::
  1412. pfnGetProc(
  1413. IN LPCSTR pszProc
  1414. ) const;
  1415. FARPROC
  1416. TLibrary::
  1417. pfnGetProc(
  1418. IN UINT uOrdinal
  1419. ) const;
  1420. HINSTANCE
  1421. TLibrary::
  1422. hInst(
  1423. VOID
  1424. ) const;
  1425. private:
  1426. HINSTANCE _hInst;
  1427. };
  1428. ///////////////////////////////////////////////////
  1429. // @@file@@ stack.hxx
  1430. ///////////////////////////////////////////////////
  1431. template<class T>
  1432. class TStack {
  1433. public:
  1434. TStack(
  1435. UINT uSize
  1436. );
  1437. ~TStack(
  1438. VOID
  1439. );
  1440. BOOL
  1441. bValid(
  1442. VOID
  1443. ) const;
  1444. BOOL
  1445. bPush(
  1446. IN T Object
  1447. );
  1448. BOOL
  1449. bPop(
  1450. IN OUT T *Object
  1451. );
  1452. UINT
  1453. uSize(
  1454. VOID
  1455. ) const;
  1456. BOOL
  1457. bEmpty(
  1458. VOID
  1459. ) const;
  1460. private:
  1461. BOOL
  1462. bGrow(
  1463. IN UINT uSize
  1464. );
  1465. UINT _uSize;
  1466. T *_pStack;
  1467. T *_pStackPtr;
  1468. };
  1469. /********************************************************************
  1470. Stack template class.
  1471. ********************************************************************/
  1472. //
  1473. // Note the _stackPtr points to the next available location.
  1474. //
  1475. template<class T>
  1476. _INLINE
  1477. TStack<T>::
  1478. TStack(
  1479. UINT uSize
  1480. ) : _uSize( uSize ),
  1481. _pStack( NULL ),
  1482. _pStackPtr( NULL )
  1483. {
  1484. _pStack = new T[_uSize+1];
  1485. if( _pStack )
  1486. {
  1487. _pStackPtr = _pStack;
  1488. }
  1489. }
  1490. template<class T>
  1491. _INLINE
  1492. TStack<T>::
  1493. ~TStack(
  1494. VOID
  1495. )
  1496. {
  1497. delete [] _pStack;
  1498. }
  1499. template<class T>
  1500. _INLINE
  1501. BOOL
  1502. TStack<T>::
  1503. bValid(
  1504. VOID
  1505. ) const
  1506. {
  1507. return _pStack != NULL;
  1508. }
  1509. template<class T>
  1510. _INLINE
  1511. BOOL
  1512. TStack<T>::
  1513. bPush(
  1514. IN T Object
  1515. )
  1516. {
  1517. SPLASSERT( _pStack );
  1518. BOOL bReturn = TRUE;
  1519. if( _pStackPtr >= _pStack + _uSize )
  1520. {
  1521. bReturn = bGrow( _uSize );
  1522. if( !bReturn )
  1523. {
  1524. DBGMSG( DBG_ERROR, ( "TStack::bPush - failed to grow\n" ) );
  1525. }
  1526. }
  1527. if( bReturn )
  1528. {
  1529. *_pStackPtr++ = Object;
  1530. bReturn = TRUE;
  1531. }
  1532. return bReturn;
  1533. }
  1534. template<class T>
  1535. _INLINE
  1536. BOOL
  1537. TStack<T>::
  1538. bPop(
  1539. OUT T *pObject
  1540. )
  1541. {
  1542. SPLASSERT( _pStack );
  1543. BOOL bReturn;
  1544. if( _pStackPtr <= _pStack )
  1545. {
  1546. bReturn = FALSE;
  1547. }
  1548. else
  1549. {
  1550. *pObject = *--_pStackPtr;
  1551. bReturn = TRUE;
  1552. }
  1553. return bReturn;
  1554. }
  1555. template<class T>
  1556. _INLINE
  1557. UINT
  1558. TStack<T>::
  1559. uSize(
  1560. VOID
  1561. ) const
  1562. {
  1563. if( _pStackPtr < _pStack || _pStackPtr > _pStack + _uSize )
  1564. {
  1565. SPLASSERT( FALSE );
  1566. }
  1567. return _pStackPtr - _pStack;
  1568. }
  1569. template<class T>
  1570. _INLINE
  1571. BOOL
  1572. TStack<T>::
  1573. bEmpty(
  1574. VOID
  1575. ) const
  1576. {
  1577. SPLASSERT( _pStack );
  1578. return _pStackPtr <= _pStack;
  1579. }
  1580. template<class T>
  1581. _INLINE
  1582. BOOL
  1583. TStack<T>::
  1584. bGrow(
  1585. IN UINT uSize
  1586. )
  1587. {
  1588. BOOL bReturn = FALSE;
  1589. //
  1590. // Calculate the new stack size.
  1591. //
  1592. UINT uNewSize = _uSize + uSize;
  1593. //
  1594. // Allocate a new stack.
  1595. //
  1596. T* pNewStack = new T[uNewSize];
  1597. if( pNewStack )
  1598. {
  1599. //
  1600. // Copy the old stack contents to the new stack;
  1601. //
  1602. for( UINT i = 0; i < _uSize; i++ )
  1603. {
  1604. pNewStack[i] = _pStack[i];
  1605. }
  1606. //
  1607. // Set the stack pointer in the new stack
  1608. //
  1609. T *pNewStackPtr = _pStackPtr - _pStack + pNewStack;
  1610. //
  1611. // Release the old stack;
  1612. //
  1613. delete [] _pStack;
  1614. //
  1615. // Set the stack pointer.
  1616. //
  1617. _pStack = pNewStack;
  1618. _uSize = uNewSize;
  1619. _pStackPtr = pNewStackPtr;
  1620. //
  1621. // Indicate the stack has grown.
  1622. //
  1623. bReturn = TRUE;
  1624. }
  1625. else
  1626. {
  1627. DBGMSG( DBG_TRACE, ( "TStack::bGrow failed.\n" ) );
  1628. }
  1629. return bReturn;
  1630. }
  1631. ///////////////////////////////////////////////////
  1632. // @@file@@ autoptr.hxx
  1633. ///////////////////////////////////////////////////
  1634. template<class T>
  1635. class auto_ptr {
  1636. public:
  1637. // Constructor
  1638. auto_ptr(
  1639. T *p = 0
  1640. );
  1641. // Destructor
  1642. ~auto_ptr(
  1643. VOID
  1644. );
  1645. // Dereference
  1646. T&
  1647. operator*(
  1648. VOID
  1649. ) const;
  1650. // Dereference
  1651. T*
  1652. operator->(
  1653. VOID
  1654. ) const;
  1655. // Return value of current dumb pointer
  1656. T*
  1657. get(
  1658. VOID
  1659. ) const;
  1660. // Relinquish ownership of current dumb pointer
  1661. T*
  1662. release(
  1663. VOID
  1664. );
  1665. // Delete owned dumb pointer
  1666. VOID
  1667. reset(
  1668. T *p
  1669. );
  1670. // Copying an auto pointer
  1671. auto_ptr(
  1672. const auto_ptr<T>& rhs
  1673. );
  1674. // Assign one auto pointer to another
  1675. const auto_ptr<T>&
  1676. operator=(
  1677. const auto_ptr<T>& rhs
  1678. );
  1679. private:
  1680. // Actual dumb pointer.
  1681. T *pointee;
  1682. };
  1683. // Constructor
  1684. template< class T >
  1685. _INLINE
  1686. auto_ptr<T>::
  1687. auto_ptr(
  1688. T *p
  1689. ) : pointee(p)
  1690. {
  1691. };
  1692. // Destructor
  1693. template< class T >
  1694. _INLINE
  1695. auto_ptr<T>::
  1696. ~auto_ptr(
  1697. VOID
  1698. )
  1699. {
  1700. delete pointee;
  1701. };
  1702. // Dereference
  1703. template< class T >
  1704. _INLINE
  1705. T&
  1706. auto_ptr<T>::
  1707. operator*(
  1708. VOID
  1709. ) const
  1710. {
  1711. return *pointee;
  1712. }
  1713. // Dereference
  1714. template< class T >
  1715. _INLINE
  1716. T*
  1717. auto_ptr<T>::
  1718. operator->(
  1719. VOID
  1720. ) const
  1721. {
  1722. return pointee;
  1723. }
  1724. // Return value of current dumb pointer
  1725. template< class T >
  1726. _INLINE
  1727. T*
  1728. auto_ptr<T>::
  1729. get(
  1730. VOID
  1731. ) const
  1732. {
  1733. return pointee;
  1734. }
  1735. // Relinquish ownership of current dumb pointer
  1736. template< class T >
  1737. _INLINE
  1738. T *
  1739. auto_ptr<T>::
  1740. release(
  1741. VOID
  1742. )
  1743. {
  1744. T *oldPointee = pointee;
  1745. pointee = 0;
  1746. return oldPointee;
  1747. }
  1748. // Delete owned dumb pointer
  1749. template< class T >
  1750. _INLINE
  1751. VOID
  1752. auto_ptr<T>::
  1753. reset(
  1754. T *p
  1755. )
  1756. {
  1757. delete pointee;
  1758. pointee = p;
  1759. }
  1760. // Copying an auto pointer
  1761. template< class T >
  1762. _INLINE
  1763. auto_ptr<T>::
  1764. auto_ptr(
  1765. const auto_ptr<T>& rhs
  1766. ) : pointee( rhs.release() )
  1767. {
  1768. }
  1769. // Assign one auto pointer to another
  1770. template< class T >
  1771. _INLINE
  1772. const auto_ptr<T>&
  1773. auto_ptr<T>::
  1774. operator=(
  1775. const auto_ptr<T>& rhs
  1776. )
  1777. {
  1778. if( this != &rhs )
  1779. {
  1780. reset( rhs.release() );
  1781. }
  1782. return *this;
  1783. }
  1784. #endif // _SPLLIB_HXX