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.

2294 lines
52 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. MRefQuick: quick ref counter, no sync done.
  682. ************************************************************/
  683. class MRefQuick : public VRef {
  684. SIGNATURE( 'refq' )
  685. ALWAYS_VALID
  686. protected:
  687. VAR( LONG, cRef );
  688. public:
  689. #if DBG
  690. MRefQuick( VOID ) : _cRef( 0 )
  691. { }
  692. ~MRefQuick( VOID )
  693. {
  694. SPLASSERT( !_cRef );
  695. }
  696. #else
  697. MRefQuick( VOID ) : _cRef( 0 )
  698. { }
  699. #endif
  700. VOID vIncRef();
  701. LONG cDecRef();
  702. VOID vDecRefDelete();
  703. };
  704. /************************************************************
  705. MRefCom: Refcount with interlocks
  706. ************************************************************/
  707. class MRefCom : public VRef {
  708. SIGNATURE( 'refc' )
  709. ALWAYS_VALID
  710. public:
  711. #if DBG
  712. MRefCom( VOID ) : _cRef( 0 )
  713. { }
  714. ~MRefCom( VOID )
  715. {
  716. SPLASSERT( !_cRef );
  717. }
  718. #else
  719. MRefCom( VOID ) : _cRef( 0 )
  720. { }
  721. #endif
  722. VOID vIncRef();
  723. LONG cDecRef();
  724. VOID vDecRefDelete();
  725. protected:
  726. //
  727. // Must be LONG, not REFCOUNT for Interlocked* apis.
  728. //
  729. VAR( LONG, cRef );
  730. virtual VOID vRefZeroed();
  731. };
  732. /************************************************************
  733. TRefLock: used to lock a VRef.
  734. ************************************************************/
  735. template<class T>
  736. class TRefLock {
  737. SIGNATURE( 'refl' )
  738. ALWAYS_VALID
  739. SAFE_NEW
  740. public:
  741. TRefLock(
  742. VOID
  743. ) : _pRef( NULL )
  744. { }
  745. TRefLock(
  746. T* pRef
  747. )
  748. {
  749. _pRef = pRef;
  750. _pRef->vIncRef( );
  751. }
  752. ~TRefLock( )
  753. {
  754. if( _pRef )
  755. _pRef->cDecRef( );
  756. }
  757. VOID vAcquire( T* pRef )
  758. {
  759. SPLASSERT( !_pRef );
  760. _pRef = pRef;
  761. _pRef->vIncRef( );
  762. }
  763. VOID vRelease( VOID )
  764. {
  765. SPLASSERT( _pRef );
  766. _pRef->cDecRef( );
  767. _pRef = NULL;
  768. }
  769. T*
  770. pGet(
  771. VOID
  772. ) const
  773. {
  774. return _pRef;
  775. }
  776. T*
  777. operator->(
  778. VOID
  779. ) const
  780. {
  781. return _pRef;
  782. }
  783. private:
  784. //
  785. // Copying and assignement not defined.
  786. //
  787. TRefLock( const TRefLock & );
  788. TRefLock & operator =(const TRefLock &);
  789. T *_pRef;
  790. };
  791. ///////////////////////////////////////////////////
  792. // @@file@@ splutil.hxx
  793. ///////////////////////////////////////////////////
  794. //
  795. // Double linked list. DLINK must be the same as DLINKBASE, except
  796. // with differnt constructors.
  797. //
  798. typedef struct DLINK {
  799. DLINK()
  800. { FLink = NULL; }
  801. DLINK* FLink;
  802. DLINK* BLink;
  803. } *PDLINK;
  804. typedef struct DLINKBASE {
  805. DLINKBASE()
  806. { FLink = BLink = (PDLINK)this; }
  807. DLINK* FLink;
  808. DLINK* BLink;
  809. } *PDLINKBASE;
  810. class TIter {
  811. public:
  812. PDLINK _pdlink;
  813. PDLINK _pdlBase;
  814. BOOL
  815. bValid()
  816. { return _pdlink != _pdlBase; }
  817. VOID
  818. vNext()
  819. { _pdlink = _pdlink->FLink; }
  820. VOID
  821. vPrev()
  822. { _pdlink = _pdlink->BLink; }
  823. operator PDLINK()
  824. { return _pdlink; }
  825. };
  826. /********************************************************************
  827. // Forward reference.
  828. class TLink;
  829. TBase has two linked lists of TLink.
  830. class TBase {
  831. DLINK_BASE( TLink, Link, Link );
  832. DLINK_BASE( TLink, Link2, Link2 );
  833. };
  834. class TLink {
  835. DLINK( TLink, Link );
  836. DLINK( TLink, Link2 );
  837. };
  838. //
  839. // Append pLink to the end of the Link2 list.
  840. //
  841. pBase->Link2_vAppend( pLink );
  842. //
  843. // Insert pLinkInsert right after pLinkMiddle.
  844. //
  845. pBase->Link_vInsert( pLinkMiddle, pLinkInsert );
  846. //
  847. // Get to the head.
  848. //
  849. pLinkHead = pBase->Link_pHead();
  850. //
  851. // To get to the next element in the list.
  852. //
  853. pLink = pLinkHead->Link_pNext();
  854. //
  855. // Remove an element from the list.
  856. //
  857. pLink->pLink_vDelinkSelf();
  858. //
  859. // Using the iter class.
  860. //
  861. TIter Iter;
  862. for( Link_vIterInit( Iter ), Iter.vNext(); Iter.bValid(); Iter.vNext( )){
  863. //
  864. // Use pLink.
  865. //
  866. vLinkOperation( pLink );
  867. }
  868. ********************************************************************/
  869. #define DLINK_BASE( type, name, linkname ) \
  870. VOID name##_vReset() \
  871. { pdl##name()->FLink = pdl##name()->BLink = pdl##name(); } \
  872. \
  873. PDLINK name##_pdlHead() const \
  874. { return pdl##name()->FLink; } \
  875. \
  876. PDLINK name##_pdlBase() const \
  877. { return pdl##name(); } \
  878. \
  879. type* name##_pHead( VOID ) const \
  880. { \
  881. return name##_bValid( name##_pdlHead() ) ? \
  882. (type*)((PBYTE)name##_pdlHead() - OFFSETOF( type, \
  883. _dl##linkname )) : \
  884. NULL; \
  885. } \
  886. \
  887. BOOL name##_bValid( PDLINK pdlink ) const \
  888. { return pdlink != pdl##name(); } \
  889. \
  890. VOID name##_vAdd( type* pType ) \
  891. { name##_vInsert( pdl##name(), pType->pdl##linkname( )); } \
  892. \
  893. VOID name##_vAppend( type* pType ) \
  894. { name##_vInsert( pdl##name()->BLink, pType->pdl##linkname( )); } \
  895. \
  896. VOID name##_vInsert( PDLINK pdlink1, type* pType2 ) \
  897. { name##_vInsert( pdlink1, pType2->pdl##linkname() ); } \
  898. \
  899. VOID name##_vInsert( PDLINK pdlink1, PDLINK pdlink2 ) \
  900. { \
  901. SPLASSERT( !pdlink2->FLink ); \
  902. pdlink1->FLink->BLink = pdlink2; \
  903. \
  904. pdlink2->BLink = pdlink1; \
  905. pdlink2->FLink = pdlink1->FLink; \
  906. \
  907. pdlink1->FLink = pdlink2; \
  908. } \
  909. \
  910. VOID name##_vInsertBefore( PDLINK pdlink1, type* pType2 ) \
  911. { name##_vInsertBefore( pdlink1, pType2->pdl##linkname() ); } \
  912. \
  913. VOID name##_vInsertBefore( PDLINK pdlink1, PDLINK pdlink2 ) \
  914. { \
  915. SPLASSERT( !pdlink2->FLink ); \
  916. pdlink1->BLink->FLink = pdlink2; \
  917. \
  918. pdlink2->FLink = pdlink1; \
  919. pdlink2->BLink = pdlink1->BLink; \
  920. \
  921. pdlink1->BLink = pdlink2; \
  922. } \
  923. \
  924. VOID name##_vDelink( type* pType ) \
  925. { name##_vDelink( pType->pdl##linkname( )); } \
  926. \
  927. VOID name##_vDelink( PDLINK pdlink ) \
  928. { \
  929. pdlink->FLink->BLink = pdlink->BLink; \
  930. pdlink->BLink->FLink = pdlink->FLink; \
  931. pdlink->FLink = NULL; \
  932. } \
  933. \
  934. type* name##_pFind( type* pType ) const \
  935. { \
  936. PDLINK pdlinkT; \
  937. PDLINK pdlink = pType->pdl##linkname(); \
  938. \
  939. for( pdlinkT = name##_pdlHead(); \
  940. name##_bValid( pdlinkT ); \
  941. pdlinkT = pdlinkT->FLink ){ \
  942. \
  943. if( pType->pdl##linkname() == pdlinkT ) \
  944. return (type*)((PBYTE)pdlink - OFFSETOF( type, \
  945. _dl##linkname )); \
  946. } \
  947. return NULL; \
  948. } \
  949. \
  950. PDLINK name##_pdlFind( PDLINK pdlink ) const \
  951. { \
  952. PDLINK pdlinkT; \
  953. for( pdlinkT = name##_pdlHead(); \
  954. name##_bValid( pdlinkT ); \
  955. pdlinkT = pdlinkT->FLink ){ \
  956. \
  957. if( pdlink == pdlinkT ) \
  958. return pdlink; \
  959. } \
  960. return NULL; \
  961. } \
  962. \
  963. PDLINK name##_pdlGetByIndex( UINT uIndex ) const \
  964. { \
  965. PDLINK pdlink; \
  966. for( pdlink = name##_pdlHead(); \
  967. uIndex; \
  968. uIndex--, pdlink = pdlink->FLink ){ \
  969. \
  970. SPLASSERT( name##_bValid( pdlink )); \
  971. } \
  972. return pdlink; \
  973. } \
  974. \
  975. type* name##_pGetByIndex( UINT uIndex ) const \
  976. { \
  977. PDLINK pdlink; \
  978. for( pdlink = name##_pdlHead(); \
  979. uIndex; \
  980. uIndex--, pdlink = pdlink->FLink ){ \
  981. \
  982. SPLASSERT( name##_bValid( pdlink )); \
  983. } \
  984. return name##_pConvert( pdlink ); \
  985. } \
  986. \
  987. static PDLINK name##_pdlNext( PDLINK pdlink ) \
  988. { return pdlink->FLink; } \
  989. \
  990. static type* name##_pConvert( PDLINK pdlink ) \
  991. { return (type*)( (PBYTE)pdlink - OFFSETOF( type, _dl##linkname )); } \
  992. \
  993. PDLINK pdl##name( VOID ) const \
  994. { return (PDLINK)&_dlb##name; } \
  995. \
  996. BOOL name##_bEmpty() const \
  997. { return pdl##name()->FLink == pdl##name(); } \
  998. \
  999. VOID name##_vIterInit( TIter& Iter ) const \
  1000. { Iter._pdlBase = Iter._pdlink = (PDLINK)&_dlb##name; } \
  1001. \
  1002. DLINKBASE _dlb##name;
  1003. \
  1004. #define DLINK( type, name ) \
  1005. PDLINK pdl##name() \
  1006. { return &_dl##name; } \
  1007. \
  1008. VOID name##_vDelinkSelf( VOID ) \
  1009. { \
  1010. _dl##name.FLink->BLink = _dl##name.BLink; \
  1011. _dl##name.BLink->FLink = _dl##name.FLink; \
  1012. _dl##name.FLink = NULL; \
  1013. } \
  1014. \
  1015. BOOL name##_bLinked() const \
  1016. { return _dl##name.FLink != NULL; } \
  1017. \
  1018. PDLINK name##_pdlNext( VOID ) const \
  1019. { return _dl##name.FLink; } \
  1020. \
  1021. PDLINK name##_pdlPrev( VOID ) const \
  1022. { return _dl##name.BLink; } \
  1023. \
  1024. type* name##_pNext( VOID ) const \
  1025. { return name##_pConvert( _dl##name.FLink ); } \
  1026. \
  1027. type* name##_pPrev( VOID ) const \
  1028. { return name##_pConvert( _dl##name.BLink ); } \
  1029. \
  1030. static type* name##_pConvert( PDLINK pdlink ) \
  1031. { return (type*)( (PBYTE)pdlink - OFFSETOF( type, _dl##name )); } \
  1032. \
  1033. DLINK _dl##name
  1034. //
  1035. // Generic MEntry class that allows objects to be stored on a list
  1036. // and searched by name.
  1037. //
  1038. class MEntry {
  1039. SIGNATURE( 'entr' )
  1040. public:
  1041. DLINK( MEntry, Entry );
  1042. TString _strName;
  1043. BOOL bValid()
  1044. {
  1045. return _strName.bValid();
  1046. }
  1047. static MEntry* pFindEntry( PDLINK pdlink, LPCTSTR pszName );
  1048. };
  1049. #define ENTRY_BASE( type, name ) \
  1050. friend MEntry; \
  1051. type* name##_pFindByName( LPCTSTR pszName ) const \
  1052. { \
  1053. MEntry* pEntry = MEntry::pFindEntry( name##_pdlBase(), pszName ); \
  1054. return pEntry ? (type*)pEntry : NULL; \
  1055. } \
  1056. static type* name##_pConvertEntry( PDLINK pdlink ) \
  1057. { \
  1058. return (type*)name##_pConvert( pdlink ); \
  1059. } \
  1060. DLINK_BASE( MEntry, name, Entry )
  1061. #define DELETE_ENTRY_LIST( type, name ) \
  1062. { \
  1063. PDLINK pdlink; \
  1064. type* pType; \
  1065. \
  1066. for( pdlink = name##_pdlHead(); name##_bValid( pdlink ); ){ \
  1067. \
  1068. pType = name##_pConvertEntry( pdlink ); \
  1069. pdlink = name##_pdlNext( pdlink ); \
  1070. \
  1071. pType->vDelete(); \
  1072. } \
  1073. }
  1074. ///////////////////////////////////////////////////
  1075. // @@file@@ threadm.hxx
  1076. ///////////////////////////////////////////////////
  1077. typedef PVOID PJOB;
  1078. class CCSLock;
  1079. class TThreadM
  1080. {
  1081. SIGNATURE( 'thdm' )
  1082. SAFE_NEW
  1083. private:
  1084. enum _States
  1085. {
  1086. kDestroyReq = 1,
  1087. kDestroyed = 2,
  1088. kPrivateCritSec = 4
  1089. } States;
  1090. /********************************************************************
  1091. Valid TMSTATUS states:
  1092. NULL -- Normal processing
  1093. DESTROY_REQ -- No new jobs, jobs possibly running
  1094. DESTROY_REQ, DESTROYED -- No new jobs, all jobs completed
  1095. ********************************************************************/
  1096. TState _State;
  1097. UINT _uIdleLife;
  1098. UINT _uMaxThreads;
  1099. UINT _uActiveThreads;
  1100. UINT _uRunNowThreads;
  1101. INT _iIdleThreads;
  1102. HANDLE _hTrigger;
  1103. CCSLock *_pCritSec;
  1104. LONG _lLocks;
  1105. DWORD
  1106. dwThreadProc(
  1107. VOID
  1108. );
  1109. static DWORD
  1110. xdwThreadProc(
  1111. PVOID pVoid
  1112. );
  1113. virtual PJOB
  1114. pThreadMJobNext(
  1115. VOID
  1116. ) = 0;
  1117. virtual VOID
  1118. vThreadMJobProcess(
  1119. PJOB pJob
  1120. ) = 0;
  1121. protected:
  1122. TThreadM(
  1123. UINT uMaxThreads,
  1124. UINT uIdleLife,
  1125. CCSLock* pCritSec
  1126. );
  1127. virtual
  1128. ~TThreadM(
  1129. VOID
  1130. );
  1131. BOOL
  1132. bValid(
  1133. VOID
  1134. ) const
  1135. {
  1136. return _hTrigger != NULL;
  1137. }
  1138. BOOL
  1139. bJobAdded(
  1140. BOOL bRunNow
  1141. );
  1142. VOID
  1143. vDelete(
  1144. VOID
  1145. );
  1146. LONG
  1147. Lock(
  1148. VOID
  1149. )
  1150. {
  1151. return InterlockedIncrement(&_lLocks);
  1152. }
  1153. LONG
  1154. Unlock(
  1155. VOID
  1156. )
  1157. {
  1158. LONG lLocks = InterlockedDecrement(&_lLocks);
  1159. if (0 == lLocks)
  1160. delete this;
  1161. return lLocks;
  1162. }
  1163. };
  1164. ///////////////////////////////////////////////////
  1165. // @@file@@ exec.hxx
  1166. ///////////////////////////////////////////////////
  1167. /********************************************************************
  1168. This module implements an asynchronous, pooled threads to
  1169. processes worker jobs.
  1170. class TJobUnit : public MExecWork {
  1171. ...
  1172. }
  1173. gpExec->bJobAdd( pJobUnit, USER_SPECIFIED_BITFIELD );
  1174. //
  1175. // When thread is available to process job,
  1176. // pJobUnit->svExecute( USER_SPECIFIED_BITFIELD, ... )
  1177. // will be called.
  1178. //
  1179. Declare a class Work derived from the mix-in MExecWork. When
  1180. work needs to be done on an instantiation of Work, it is queued
  1181. and immediately returned. A DWORD bitfield--4 high bits are
  1182. predefined--indicates the type of work needed.
  1183. This DWORD should be a bitfield, so if there are multiple
  1184. bJobAdd requests and all threads are busy, these DWORDs are
  1185. OR'd together.
  1186. That is,
  1187. bJobAdd( pJobUnit, 0x1 );
  1188. bJobAdd( pJobUnit, 0x2 );
  1189. bJobAdd( pJobUnit, 0x4 );
  1190. bJobAdd( pJobUnit, 0x8 );
  1191. We will call svExecute with 0xf.
  1192. Two threads will never operate on one job simultaneously. This
  1193. is guarenteed by this library.
  1194. The worker routine is defined by the virtual function stExecute().
  1195. ********************************************************************/
  1196. typedef enum _STATE_EXEC {
  1197. kExecUser = 0x08000000, // Here and below user may specify.
  1198. kExecRunNow = 0x10000000, // Ignore thread limit.
  1199. kExecExit = 0x20000000, // User requests the TExec exits.
  1200. kExecActive = 0x40000000, // Private: job is actively running.
  1201. kExecActiveReq = 0x80000000, // Private: job is queued.
  1202. kExecPrivate = kExecActive | kExecActiveReq,
  1203. kExecNoOutput = kExecPrivate | kExecRunNow
  1204. } STATE_EXEC;
  1205. class TExec;
  1206. class MExecWork {
  1207. friend TExec;
  1208. SIGNATURE( 'exwk' );
  1209. ALWAYS_VALID
  1210. SAFE_NEW
  1211. private:
  1212. DLINK( MExecWork, Work );
  1213. //
  1214. // Accessed by worker thread.
  1215. //
  1216. VAR( TState, State );
  1217. //
  1218. // StatePending is work that is pending (accumulated while the
  1219. // job is executing in a thread). The job at this stage is
  1220. // not in the queue.
  1221. //
  1222. VAR( TState, StatePending );
  1223. virtual
  1224. STATEVAR
  1225. svExecute(
  1226. STATEVAR StateVar
  1227. ) = 0;
  1228. virtual
  1229. VOID
  1230. vExecFailedAddJob(
  1231. VOID
  1232. ) = 0;
  1233. /********************************************************************
  1234. vExecExitComplete is called when a job completes and it is
  1235. pending deletion. This allows a client to allow all pending
  1236. work to complete before it deletes the object.
  1237. User adds job.
  1238. Job starts executing..,
  1239. User decides job should be deleted so adds EXEC_EXIT.
  1240. ... job finally completes.
  1241. Library calls vExecExitComplete on job
  1242. Client can now delete work object in vExecExitComplete call.
  1243. Note that only jobs that are currently executing are allowed
  1244. to complete. Jobs that are queued to work will exit immediately.
  1245. ********************************************************************/
  1246. virtual
  1247. VOID
  1248. vExecExitComplete(
  1249. VOID
  1250. ) = 0;
  1251. };
  1252. class TExec : public TThreadM {
  1253. SIGNATURE( 'exec' );
  1254. SAFE_NEW
  1255. public:
  1256. TExec( CCSLock* pCritSec );
  1257. //
  1258. // Clients should use vDelete, _not_ ~TExec.
  1259. //
  1260. ~TExec(
  1261. VOID
  1262. )
  1263. { }
  1264. VOID
  1265. vDelete(
  1266. VOID
  1267. )
  1268. {
  1269. TThreadM::vDelete();
  1270. }
  1271. BOOL
  1272. bValid(
  1273. VOID
  1274. ) const
  1275. {
  1276. return TThreadM::bValid();
  1277. }
  1278. BOOL
  1279. bJobAdd(
  1280. MExecWork* pExecWork,
  1281. STATEVAR StateVar
  1282. );
  1283. VOID
  1284. vJobDone(
  1285. MExecWork* pExecWork,
  1286. STATEVAR StateVar
  1287. );
  1288. STATEVAR
  1289. svClearPendingWork(
  1290. MExecWork* pExecWork
  1291. );
  1292. private:
  1293. DLINK_BASE( MExecWork, Work, Work );
  1294. CCSLock* _pCritSec;
  1295. //
  1296. // Virtual definitions for TThreadM.
  1297. //
  1298. PJOB
  1299. pThreadMJobNext(
  1300. VOID
  1301. );
  1302. VOID
  1303. vThreadMJobProcess(
  1304. PJOB pJob
  1305. );
  1306. BOOL
  1307. bJobAddWorker(
  1308. MExecWork* pExecWork
  1309. );
  1310. };
  1311. ///////////////////////////////////////////////////
  1312. // @@file@@ mem.hxx
  1313. ///////////////////////////////////////////////////
  1314. #define AllocMem(cb) malloc(cb)
  1315. #define FreeMem(ptr) free(ptr)
  1316. ///////////////////////////////////////////////////
  1317. // @@file@@ bitarray.hxx
  1318. ///////////////////////////////////////////////////
  1319. class TBitArray {
  1320. public:
  1321. typedef UINT Type;
  1322. enum {
  1323. kBitsInType = sizeof( Type ) * 8,
  1324. kBitsInTypeMask = 0xFFFFFFFF,
  1325. };
  1326. TBitArray(
  1327. IN UINT uBits = kBitsInType,
  1328. IN UINT uGrowSize = kBitsInType
  1329. );
  1330. TBitArray(
  1331. IN const TBitArray &rhs
  1332. );
  1333. const TBitArray &
  1334. operator=(
  1335. IN const TBitArray &rhs
  1336. );
  1337. ~TBitArray(
  1338. VOID
  1339. );
  1340. BOOL
  1341. bValid(
  1342. VOID
  1343. ) const;
  1344. BOOL
  1345. bToString( // Return string representation of bit array
  1346. IN TString &strBits
  1347. ) const;
  1348. BOOL
  1349. bRead(
  1350. IN UINT uBit // Range 0 to nBit - 1
  1351. ) const;
  1352. BOOL
  1353. bSet(
  1354. IN UINT uBit // Range 0 to nBit - 1
  1355. );
  1356. BOOL
  1357. bReset(
  1358. IN UINT uBit // Range 0 to nBit - 1
  1359. );
  1360. BOOL
  1361. bToggle(
  1362. IN UINT uBit // Range 0 to nBit - 1
  1363. );
  1364. BOOL
  1365. bAdd(
  1366. VOID // Add one bit to the array
  1367. );
  1368. UINT
  1369. uNumBits( // Return the total number of bits in the array
  1370. VOID
  1371. ) const;
  1372. VOID
  1373. vSetAll( // Set all the bits in the array
  1374. VOID
  1375. );
  1376. VOID
  1377. vResetAll( // Reset all the bits in the array
  1378. VOID
  1379. );
  1380. BOOL
  1381. bFindNextResetBit( // Locate first cleared bit in the array
  1382. IN UINT *puNextFreeBit
  1383. );
  1384. private:
  1385. BOOL
  1386. bClone( // Make a copy of the bit array
  1387. IN const TBitArray &rhs
  1388. );
  1389. BOOL
  1390. bGrow( // Expand the bit array by x number of bits
  1391. IN UINT uGrowSize
  1392. );
  1393. UINT
  1394. nBitsToType(
  1395. IN UINT uBits // Range 1 to nBit
  1396. ) const;
  1397. Type
  1398. BitToMask(
  1399. IN UINT uBit // Range 0 to nBit - 1
  1400. ) const;
  1401. UINT
  1402. BitToIndex(
  1403. IN UINT uBit // Range 0 to nBit - 1
  1404. ) const;
  1405. BOOL
  1406. bIsValidBit(
  1407. IN UINT uBit // Range 0 to nBit - 1
  1408. ) const;
  1409. UINT _nBits; // Number of currently allocated bits, Range 1 to n
  1410. Type *_pBits; // Pointer to array which contains the bits
  1411. UINT _uGrowSize; // Default number of bits to grow by
  1412. };
  1413. ///////////////////////////////////////////////////
  1414. // @@file@@ loadlib.hxx
  1415. ///////////////////////////////////////////////////
  1416. /********************************************************************
  1417. Helper class to load and release a DLL. Use the bValid for
  1418. library load validation.
  1419. ********************************************************************/
  1420. class TLibrary {
  1421. public:
  1422. TLibrary::
  1423. TLibrary(
  1424. IN LPCTSTR pszLibName
  1425. );
  1426. TLibrary::
  1427. ~TLibrary(
  1428. );
  1429. BOOL
  1430. TLibrary::
  1431. bValid(
  1432. VOID
  1433. ) const;
  1434. FARPROC
  1435. TLibrary::
  1436. pfnGetProc(
  1437. IN LPCSTR pszProc
  1438. ) const;
  1439. FARPROC
  1440. TLibrary::
  1441. pfnGetProc(
  1442. IN UINT uOrdinal
  1443. ) const;
  1444. HINSTANCE
  1445. TLibrary::
  1446. hInst(
  1447. VOID
  1448. ) const;
  1449. private:
  1450. HINSTANCE _hInst;
  1451. };
  1452. ///////////////////////////////////////////////////
  1453. // @@file@@ stack.hxx
  1454. ///////////////////////////////////////////////////
  1455. template<class T>
  1456. class TStack {
  1457. public:
  1458. TStack(
  1459. UINT uSize
  1460. );
  1461. ~TStack(
  1462. VOID
  1463. );
  1464. BOOL
  1465. bValid(
  1466. VOID
  1467. ) const;
  1468. BOOL
  1469. bPush(
  1470. IN T Object
  1471. );
  1472. BOOL
  1473. bPop(
  1474. IN OUT T *Object
  1475. );
  1476. UINT
  1477. uSize(
  1478. VOID
  1479. ) const;
  1480. BOOL
  1481. bEmpty(
  1482. VOID
  1483. ) const;
  1484. private:
  1485. BOOL
  1486. bGrow(
  1487. IN UINT uSize
  1488. );
  1489. UINT _uSize;
  1490. T *_pStack;
  1491. T *_pStackPtr;
  1492. };
  1493. /********************************************************************
  1494. Stack template class.
  1495. ********************************************************************/
  1496. //
  1497. // Note the _stackPtr points to the next available location.
  1498. //
  1499. template<class T>
  1500. _INLINE
  1501. TStack<T>::
  1502. TStack(
  1503. UINT uSize
  1504. ) : _uSize( uSize ),
  1505. _pStack( NULL ),
  1506. _pStackPtr( NULL )
  1507. {
  1508. _pStack = new T[_uSize+1];
  1509. if( _pStack )
  1510. {
  1511. _pStackPtr = _pStack;
  1512. }
  1513. }
  1514. template<class T>
  1515. _INLINE
  1516. TStack<T>::
  1517. ~TStack(
  1518. VOID
  1519. )
  1520. {
  1521. delete [] _pStack;
  1522. }
  1523. template<class T>
  1524. _INLINE
  1525. BOOL
  1526. TStack<T>::
  1527. bValid(
  1528. VOID
  1529. ) const
  1530. {
  1531. return _pStack != NULL;
  1532. }
  1533. template<class T>
  1534. _INLINE
  1535. BOOL
  1536. TStack<T>::
  1537. bPush(
  1538. IN T Object
  1539. )
  1540. {
  1541. SPLASSERT( _pStack );
  1542. BOOL bReturn = TRUE;
  1543. if( _pStackPtr >= _pStack + _uSize )
  1544. {
  1545. bReturn = bGrow( _uSize );
  1546. if( !bReturn )
  1547. {
  1548. DBGMSG( DBG_ERROR, ( "TStack::bPush - failed to grow\n" ) );
  1549. }
  1550. }
  1551. if( bReturn )
  1552. {
  1553. *_pStackPtr++ = Object;
  1554. bReturn = TRUE;
  1555. }
  1556. return bReturn;
  1557. }
  1558. template<class T>
  1559. _INLINE
  1560. BOOL
  1561. TStack<T>::
  1562. bPop(
  1563. OUT T *pObject
  1564. )
  1565. {
  1566. SPLASSERT( _pStack );
  1567. BOOL bReturn;
  1568. if( _pStackPtr <= _pStack )
  1569. {
  1570. bReturn = FALSE;
  1571. }
  1572. else
  1573. {
  1574. *pObject = *--_pStackPtr;
  1575. bReturn = TRUE;
  1576. }
  1577. return bReturn;
  1578. }
  1579. template<class T>
  1580. _INLINE
  1581. UINT
  1582. TStack<T>::
  1583. uSize(
  1584. VOID
  1585. ) const
  1586. {
  1587. if( _pStackPtr < _pStack || _pStackPtr > _pStack + _uSize )
  1588. {
  1589. SPLASSERT( FALSE );
  1590. }
  1591. return _pStackPtr - _pStack;
  1592. }
  1593. template<class T>
  1594. _INLINE
  1595. BOOL
  1596. TStack<T>::
  1597. bEmpty(
  1598. VOID
  1599. ) const
  1600. {
  1601. SPLASSERT( _pStack );
  1602. return _pStackPtr <= _pStack;
  1603. }
  1604. template<class T>
  1605. _INLINE
  1606. BOOL
  1607. TStack<T>::
  1608. bGrow(
  1609. IN UINT uSize
  1610. )
  1611. {
  1612. BOOL bReturn = FALSE;
  1613. //
  1614. // Calculate the new stack size.
  1615. //
  1616. UINT uNewSize = _uSize + uSize;
  1617. //
  1618. // Allocate a new stack.
  1619. //
  1620. T* pNewStack = new T[uNewSize];
  1621. if( pNewStack )
  1622. {
  1623. //
  1624. // Copy the old stack contents to the new stack;
  1625. //
  1626. for( UINT i = 0; i < _uSize; i++ )
  1627. {
  1628. pNewStack[i] = _pStack[i];
  1629. }
  1630. //
  1631. // Set the stack pointer in the new stack
  1632. //
  1633. T *pNewStackPtr = _pStackPtr - _pStack + pNewStack;
  1634. //
  1635. // Release the old stack;
  1636. //
  1637. delete [] _pStack;
  1638. //
  1639. // Set the stack pointer.
  1640. //
  1641. _pStack = pNewStack;
  1642. _uSize = uNewSize;
  1643. _pStackPtr = pNewStackPtr;
  1644. //
  1645. // Indicate the stack has grown.
  1646. //
  1647. bReturn = TRUE;
  1648. }
  1649. else
  1650. {
  1651. DBGMSG( DBG_TRACE, ( "TStack::bGrow failed.\n" ) );
  1652. }
  1653. return bReturn;
  1654. }
  1655. ///////////////////////////////////////////////////
  1656. // @@file@@ autoptr.hxx
  1657. ///////////////////////////////////////////////////
  1658. template<class T>
  1659. class auto_ptr {
  1660. public:
  1661. // Constructor
  1662. auto_ptr(
  1663. T *p = 0
  1664. );
  1665. // Destructor
  1666. ~auto_ptr(
  1667. VOID
  1668. );
  1669. // Dereference
  1670. T&
  1671. operator*(
  1672. VOID
  1673. ) const;
  1674. // Dereference
  1675. T*
  1676. operator->(
  1677. VOID
  1678. ) const;
  1679. // Return value of current dumb pointer
  1680. T*
  1681. get(
  1682. VOID
  1683. ) const;
  1684. // Relinquish ownership of current dumb pointer
  1685. T*
  1686. release(
  1687. VOID
  1688. );
  1689. // Delete owned dumb pointer
  1690. VOID
  1691. reset(
  1692. T *p
  1693. );
  1694. // Copying an auto pointer
  1695. auto_ptr(
  1696. const auto_ptr<T>& rhs
  1697. );
  1698. // Assign one auto pointer to another
  1699. const auto_ptr<T>&
  1700. operator=(
  1701. const auto_ptr<T>& rhs
  1702. );
  1703. private:
  1704. // Actual dumb pointer.
  1705. T *pointee;
  1706. };
  1707. // Constructor
  1708. template< class T >
  1709. _INLINE
  1710. auto_ptr<T>::
  1711. auto_ptr(
  1712. T *p
  1713. ) : pointee(p)
  1714. {
  1715. };
  1716. // Destructor
  1717. template< class T >
  1718. _INLINE
  1719. auto_ptr<T>::
  1720. ~auto_ptr(
  1721. VOID
  1722. )
  1723. {
  1724. delete pointee;
  1725. };
  1726. // Dereference
  1727. template< class T >
  1728. _INLINE
  1729. T&
  1730. auto_ptr<T>::
  1731. operator*(
  1732. VOID
  1733. ) const
  1734. {
  1735. return *pointee;
  1736. }
  1737. // Dereference
  1738. template< class T >
  1739. _INLINE
  1740. T*
  1741. auto_ptr<T>::
  1742. operator->(
  1743. VOID
  1744. ) const
  1745. {
  1746. return pointee;
  1747. }
  1748. // Return value of current dumb pointer
  1749. template< class T >
  1750. _INLINE
  1751. T*
  1752. auto_ptr<T>::
  1753. get(
  1754. VOID
  1755. ) const
  1756. {
  1757. return pointee;
  1758. }
  1759. // Relinquish ownership of current dumb pointer
  1760. template< class T >
  1761. _INLINE
  1762. T *
  1763. auto_ptr<T>::
  1764. release(
  1765. VOID
  1766. )
  1767. {
  1768. T *oldPointee = pointee;
  1769. pointee = 0;
  1770. return oldPointee;
  1771. }
  1772. // Delete owned dumb pointer
  1773. template< class T >
  1774. _INLINE
  1775. VOID
  1776. auto_ptr<T>::
  1777. reset(
  1778. T *p
  1779. )
  1780. {
  1781. delete pointee;
  1782. pointee = p;
  1783. }
  1784. // Copying an auto pointer
  1785. template< class T >
  1786. _INLINE
  1787. auto_ptr<T>::
  1788. auto_ptr(
  1789. const auto_ptr<T>& rhs
  1790. ) : pointee( rhs.release() )
  1791. {
  1792. }
  1793. // Assign one auto pointer to another
  1794. template< class T >
  1795. _INLINE
  1796. const auto_ptr<T>&
  1797. auto_ptr<T>::
  1798. operator=(
  1799. const auto_ptr<T>& rhs
  1800. )
  1801. {
  1802. if( this != &rhs )
  1803. {
  1804. reset( rhs.release() );
  1805. }
  1806. return *this;
  1807. }
  1808. #endif // _SPLLIB_HXX