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.

1053 lines
28 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1991 - 2000.
  5. //
  6. // File: BITSTM.cxx
  7. //
  8. // Contents: 'Bit Stream'
  9. //
  10. // Classes: CBitBuffer
  11. //
  12. // Classes: CBitStream, CWBitStream, CRBitStream
  13. //
  14. // History: 03-Jul-91 KyleP Created
  15. // 24-Aug-92 BartoszM Rewrote it
  16. //
  17. //----------------------------------------------------------------------------
  18. #include <pch.cxx>
  19. #pragma hdrstop
  20. #pragma optimize( "t", on )
  21. #include "bitstm.hxx"
  22. //+---------------------------------------------------------------------------
  23. //
  24. // Member: CSmartBuffer::CSmartBuffer, public
  25. //
  26. // Synopsis: Constructor.
  27. //
  28. // Arguments: [phStorage] -- Physical index -- source of pages
  29. // [mode] -- Access mode for the index
  30. //
  31. // History: 02-Sep-92 BartoszM Created
  32. //
  33. //----------------------------------------------------------------------------
  34. CSmartBuffer::CSmartBuffer ( CPhysStorage& phStorage, EAccessMode mode )
  35. : _phStorage(phStorage),
  36. _pBuffer(0),
  37. _fWritable( mode == eWriteExisting )
  38. {
  39. }
  40. //+---------------------------------------------------------------------------
  41. //
  42. // Member: CSmartBuffer::CSmartBuffer, public
  43. //
  44. // Synopsis: Constructor.
  45. //
  46. // Arguments: [phStorage] -- Physical index -- source of pages
  47. // [fCreate] -- Indicates if new buffer is needed
  48. //
  49. // History: 02-Sep-92 BartoszM Created
  50. //
  51. //----------------------------------------------------------------------------
  52. CSmartBuffer::CSmartBuffer ( CPhysStorage& phStorage, BOOL fCreate )
  53. : _phStorage(phStorage),
  54. _numPage(0),
  55. _fWritable(fCreate)
  56. {
  57. if (fCreate)
  58. {
  59. _pBuffer = _phStorage.BorrowNewBuffer(0);
  60. IncrementSig();
  61. #if CIDBG == 1
  62. CheckCorruption();
  63. #endif
  64. }
  65. else
  66. {
  67. _pBuffer = _phStorage.BorrowBuffer( 0, _fWritable, _fWritable );
  68. CheckCorruption();
  69. }
  70. }
  71. //+---------------------------------------------------------------------------
  72. //
  73. // Member: CSmartBuffer::CSmartBuffer, public
  74. //
  75. // Synopsis: Constructor.
  76. //
  77. // Arguments: [phStorage] -- Physical index -- source of pages
  78. // [numPage] -- Page to encapsulate
  79. // [mode] -- Access mode for the index
  80. // [fIncrSig] -- Indicates if page should be signed
  81. //
  82. // History: 02-Sep-92 BartoszM Created
  83. //
  84. //----------------------------------------------------------------------------
  85. CSmartBuffer::CSmartBuffer ( CPhysStorage& phStorage,
  86. ULONG numPage,
  87. EAccessMode mode,
  88. BOOL fIncrSig )
  89. : _phStorage(phStorage),
  90. _numPage(numPage),
  91. _fWritable(mode == eWriteExisting)
  92. {
  93. _pBuffer = _phStorage.BorrowBuffer( _numPage, _fWritable, _fWritable );
  94. if ( _fWritable && fIncrSig )
  95. IncrementSig();
  96. if (fIncrSig)
  97. CheckCorruption();
  98. }
  99. //+---------------------------------------------------------------------------
  100. //
  101. // Member: CSmartBuffer::CSmartBuffer, public
  102. //
  103. // Synopsis: Constructor.
  104. //
  105. // Arguments: [buf] -- Source CSmartBuffer
  106. // [numPage] -- Page to acquire
  107. //
  108. // History: 02-Sep-92 BartoszM Created
  109. //
  110. //----------------------------------------------------------------------------
  111. CSmartBuffer::CSmartBuffer ( CSmartBuffer& buf, ULONG numPage )
  112. : _phStorage(buf._phStorage),
  113. _numPage(numPage),
  114. _fWritable(buf._fWritable)
  115. {
  116. _pBuffer = _phStorage.BorrowBuffer( _numPage, _fWritable, _fWritable );
  117. if ( _fWritable )
  118. IncrementSig();
  119. CheckCorruption();
  120. }
  121. //+---------------------------------------------------------------------------
  122. //
  123. // Member: CSmartBuffer::~CSmartBuffer, public
  124. //
  125. // Synopsis: Destructor.
  126. //
  127. // History: 02-Sep-92 BartoszM Created
  128. //
  129. //----------------------------------------------------------------------------
  130. CSmartBuffer::~CSmartBuffer ()
  131. {
  132. if ( 0 != _pBuffer )
  133. {
  134. // If a writable buffer still exists in this destructor we're in a
  135. // failure path that must not THROW. Anything that really needs to
  136. // be on disk should already be there by now, so this code path
  137. // won't throw if it can't flush.
  138. //
  139. // If you see this debugout and you're not unwinding an exception,
  140. // your code is broken.
  141. // If a merge fails and you get this debugout, it's not a problem
  142. //
  143. if ( _fWritable && _phStorage.RequiresFlush( _numPage ) )
  144. {
  145. IncrementSig();
  146. ciDebugOut(( DEB_WARN, "deleting writable buffer in potential "
  147. "unwind path -- it may not get flushed\n" ));
  148. }
  149. _phStorage.ReturnBuffer( _numPage, _fWritable, FALSE );
  150. }
  151. }
  152. //+---------------------------------------------------------------------------
  153. //
  154. // Member: CSmartBuffer::CheckCorruption, private
  155. //
  156. // Synopsis: Attempts to determine if the entire page wasn't written
  157. // to disk.
  158. //
  159. // History: ? KyleP Created
  160. //
  161. //----------------------------------------------------------------------------
  162. void CSmartBuffer::CheckCorruption()
  163. {
  164. if ( 0 == _pBuffer[0] ||
  165. _pBuffer[0] != _pBuffer[SMARTBUF_PAGE_SIZE_IN_DWORDS + 1] )
  166. {
  167. ciDebugOut(( DEB_ERROR, "Buffer at 0x%x corrupt (StartDword = 0x%x, EndDword = 0x%x)\n",
  168. _pBuffer, _pBuffer[0], _pBuffer[SMARTBUF_PAGE_SIZE_IN_DWORDS + 1] ));
  169. Win4Assert( !"Index corruption." );
  170. _phStorage.GetStorage().ReportCorruptComponent( ( 0 == _pBuffer[0] ) ?
  171. L"SmartBuffer1" :
  172. L"SmartBuffer2");
  173. THROW( CException( CI_CORRUPT_DATABASE ) );
  174. }
  175. }
  176. //+---------------------------------------------------------------------------
  177. //
  178. // Member: CSmartBuffer::IncrementSig, private
  179. //
  180. // Synopsis: Increments the signature at the start and end of the page.
  181. //
  182. // History: ? KyleP Created
  183. //
  184. //----------------------------------------------------------------------------
  185. void CSmartBuffer::IncrementSig()
  186. {
  187. Win4Assert( _pBuffer[0] == _pBuffer[SMARTBUF_PAGE_SIZE_IN_DWORDS + 1] );
  188. _pBuffer[0]++;
  189. _pBuffer[SMARTBUF_PAGE_SIZE_IN_DWORDS + 1]++;
  190. }
  191. //+---------------------------------------------------------------------------
  192. //
  193. // Member: CSmartBuffer::InitSignature, public
  194. //
  195. // Synopsis: Initializes the signature at the start and end of the page.
  196. //
  197. // History: ? KyleP Created
  198. //
  199. //----------------------------------------------------------------------------
  200. void CSmartBuffer::InitSignature()
  201. {
  202. _pBuffer[0] = _pBuffer[SMARTBUF_PAGE_SIZE_IN_DWORDS + 1] = 1;
  203. }
  204. //+---------------------------------------------------------------------------
  205. //
  206. // Member: CSmartBuffer::Refill, public
  207. //
  208. // Synopsis: Makes sure the given page is borrowed and ready to go
  209. //
  210. // Arguments: [numPage] -- The page requested
  211. //
  212. // History: 11/6/98 dlee Added Header
  213. //
  214. //----------------------------------------------------------------------------
  215. void CSmartBuffer::Refill( ULONG numPage )
  216. {
  217. if ( 0 != _pBuffer &&
  218. _fWritable &&
  219. _phStorage.RequiresFlush( _numPage ) )
  220. {
  221. IncrementSig();
  222. }
  223. // first borrow next, then return previous to avoid reloading
  224. ULONG * pOld = _pBuffer;
  225. unsigned numOldPage = _numPage;
  226. _pBuffer = _phStorage.BorrowBuffer( numPage, _fWritable, _fWritable );
  227. _numPage = numPage;
  228. if ( 0 != pOld )
  229. _phStorage.ReturnBuffer( numOldPage, _fWritable );
  230. Win4Assert( 0 != _pBuffer );
  231. // increment signature
  232. if ( _fWritable )
  233. IncrementSig();
  234. CheckCorruption();
  235. }
  236. //+---------------------------------------------------------------------------
  237. //
  238. // Member: CSmartBuffer::Next, public
  239. //
  240. // Synopsis: Makes sure the next page is borrowed and ready to go
  241. //
  242. // History: 11/6/98 dlee Added Header
  243. //
  244. //----------------------------------------------------------------------------
  245. ULONG* CSmartBuffer::Next()
  246. {
  247. Win4Assert( 0 != _pBuffer );
  248. if ( 0 != _pBuffer &&
  249. _fWritable &&
  250. _phStorage.RequiresFlush( _numPage ) )
  251. IncrementSig();
  252. ULONG * pOld = _pBuffer;
  253. // first borrow next, then return previous to avoid reloading
  254. _pBuffer = _phStorage.BorrowBuffer( _numPage+1, _fWritable, _fWritable );
  255. _numPage++;
  256. if ( 0 != pOld )
  257. _phStorage.ReturnBuffer( _numPage-1, _fWritable );
  258. Win4Assert( 0 != _pBuffer );
  259. if ( _fWritable )
  260. IncrementSig();
  261. CheckCorruption();
  262. return _pBuffer + 1;
  263. }
  264. //+---------------------------------------------------------------------------
  265. //
  266. // Member: CSmartBuffer::NextNew, public
  267. //
  268. // Synopsis: Makes sure the next page is borrowed and ready to go
  269. //
  270. // History: 11/6/98 dlee Added Header
  271. //
  272. //----------------------------------------------------------------------------
  273. ULONG* CSmartBuffer::NextNew()
  274. {
  275. Win4Assert( 0 != _pBuffer );
  276. if ( _fWritable && _phStorage.RequiresFlush( _numPage ) )
  277. IncrementSig();
  278. // first borrow next, then return previous to avoid reloading
  279. _pBuffer = _phStorage.BorrowNewBuffer(_numPage+1);
  280. _numPage++;
  281. Win4Assert ( _pBuffer != 0 );
  282. _phStorage.ReturnBuffer( _numPage-1, _fWritable );
  283. if ( _fWritable )
  284. IncrementSig();
  285. #if CIDBG == 1
  286. CheckCorruption();
  287. #endif
  288. return _pBuffer + 1;
  289. }
  290. //+---------------------------------------------------------------------------
  291. //
  292. // Member: CSmartBuffer::Free, public
  293. //
  294. // Synopsis: Frees the current page if and only if the underlying storage
  295. // is writable. Useful for master merges where we want to
  296. // unmap the old master index so it can be made sparse.
  297. //
  298. // History: 11/6/98 dlee Added Header
  299. //
  300. //----------------------------------------------------------------------------
  301. void CSmartBuffer::Free()
  302. {
  303. //
  304. // Only free the buffer if the stream (not necessarily the buffer)
  305. // is writable, so the stream can be shrunk from the front during a
  306. // master merge.
  307. //
  308. Win4Assert( _phStorage.IsWritable() );
  309. if ( 0 != _pBuffer )
  310. {
  311. if ( _fWritable && _phStorage.RequiresFlush( _numPage ) )
  312. IncrementSig();
  313. _phStorage.ReturnBuffer( _numPage, _fWritable );
  314. _pBuffer = 0;
  315. }
  316. }
  317. //+---------------------------------------------------------------------------
  318. //
  319. // Member: CBitStream::CBitStream, public
  320. //
  321. // Synopsis: Constructor. Does not load pages.
  322. //
  323. // Arguments: [physIndex] -- Physical index -- source of pages
  324. //
  325. // History: 02-Sep-92 BartoszM Created
  326. //
  327. //----------------------------------------------------------------------------
  328. CBitStream::CBitStream(CPhysStorage& phStorage, CSmartBuffer::EAccessMode mode )
  329. : _buffer(phStorage, mode),
  330. _oBuffer( 0 )
  331. {
  332. }
  333. //+---------------------------------------------------------------------------
  334. //
  335. // Member: CPBitStream::CPBitStream, public
  336. //
  337. // Synopsis: Constructor. Does not load any pages.
  338. //
  339. // Arguments: [physIndex] -- Physical index -- source of pages
  340. //
  341. // History: 02-Sep-92 BartoszM Created
  342. //
  343. //----------------------------------------------------------------------------
  344. CPBitStream::CPBitStream(CPhysStorage& phStorage)
  345. : CBitStream ( phStorage, CSmartBuffer::eWriteExisting )
  346. {
  347. _bitOff.SetPage(0);
  348. _bitOff.SetOff(0);
  349. ciDebugOut (( DEB_BITSTM, "CPBitStream::CPBitStream\n" ));
  350. }
  351. //+---------------------------------------------------------------------------
  352. //
  353. // Member: CBitStream::CBitStream, public
  354. //
  355. // Synopsis: Constructor. Starts at the beginning of index
  356. //
  357. // Arguments: [physIndex] -- Physical index -- source of pages
  358. //
  359. // History: 08-Jul-91 KyleP Created.
  360. //
  361. //----------------------------------------------------------------------------
  362. CBitStream::CBitStream(CPhysStorage& phStorage, BOOL fCreate)
  363. : _buffer(phStorage, fCreate),
  364. _oBuffer( 0 )
  365. {
  366. ciDebugOut (( DEB_BITSTM, "CBitStream::CBitStream\n" ));
  367. _pCurPos = _buffer.Get();
  368. _pEndBuf = _pCurPos + SMARTBUF_PAGE_SIZE_IN_DWORDS;
  369. _cbitLeftDW = ULONG_BITS;
  370. }
  371. //+---------------------------------------------------------------------------
  372. //
  373. // Member: CBitStream::CBitStream, public
  374. //
  375. // Synopsis: Constructor. Seek to a specified position.
  376. //
  377. // Arguments: [physIndex] -- Physical index -- source of pages
  378. // [off] -- starting bit offset
  379. // [mode] -- Check access mode
  380. // [fIncrSig] -- Indicates if signature has to be incremented.
  381. //
  382. // History: 08-Jul-91 KyleP Created.
  383. //
  384. //----------------------------------------------------------------------------
  385. CBitStream::CBitStream(CPhysStorage& phStorage,
  386. const BitOffset& off,
  387. CSmartBuffer::EAccessMode mode,
  388. BOOL fIncrSig )
  389. : _buffer(phStorage, off.Page(), mode, fIncrSig),
  390. _oBuffer( 0 )
  391. {
  392. ciDebugOut(( DEB_BITSTM, "CBitStream::CBitStream %d:%d\n",
  393. off.Page(), off.Offset() ));
  394. SetPosition(off.Offset());
  395. }
  396. //+---------------------------------------------------------------------------
  397. //
  398. // Member: CBitStream::LoadNextPage, private
  399. //
  400. // Synopsis: Loads next page, positions stream at its beginning
  401. //
  402. // Requires: Page must already exits
  403. //
  404. // History: 28-Aug-92 BartoszM Created.
  405. //
  406. //----------------------------------------------------------------------------
  407. void CBitStream::LoadNextPage()
  408. {
  409. _pCurPos = _buffer.Next();
  410. _pEndBuf = _pCurPos + SMARTBUF_PAGE_SIZE_IN_DWORDS;
  411. _cbitLeftDW = ULONG_BITS;
  412. }
  413. //+---------------------------------------------------------------------------
  414. //
  415. // Member: CBitStream::LoadNewPage, private
  416. //
  417. // Synopsis: Creates and loads new page following the current one
  418. // Positions stream at its beginning
  419. //
  420. // History: 28-Aug-92 BartoszM Created.
  421. //
  422. // Notice: Page should be zero filled
  423. //
  424. //----------------------------------------------------------------------------
  425. void CBitStream::LoadNewPage()
  426. {
  427. _pCurPos = _buffer.NextNew();
  428. _pEndBuf = _pCurPos + SMARTBUF_PAGE_SIZE_IN_DWORDS;
  429. _cbitLeftDW = ULONG_BITS;
  430. #if CIDBG == 1
  431. ULONG* p = _buffer.Get();
  432. for (int i=0; i < SMARTBUF_PAGE_SIZE_IN_DWORDS; i++)
  433. if (p[i] != 0)
  434. break;
  435. Win4Assert(i == SMARTBUF_PAGE_SIZE_IN_DWORDS);
  436. #endif
  437. }
  438. //+---------------------------------------------------------------------------
  439. //
  440. // Function: Refill
  441. //
  442. // Synopsis: Invalidates the currently cached copy and gets a new
  443. // copy of the buffer. This is needed during master merge
  444. // because we unmap the buffer before flushing and it is
  445. // possible that the re-mapped buffer may be in a physically
  446. // different location.
  447. //
  448. // History: 4-20-94 srikants Created
  449. //
  450. // Notes:
  451. //
  452. //----------------------------------------------------------------------------
  453. void CBitStream::Refill()
  454. {
  455. BitOffset bitOff;
  456. GetOffset(bitOff);
  457. _buffer.Refill(bitOff.Page());
  458. SetPosition( bitOff.Offset() );
  459. }
  460. //+---------------------------------------------------------------------------
  461. //
  462. // Member: CBitStream::SetPosition, private
  463. //
  464. // Synopsis: Set bit position within a freshly loaded page
  465. //
  466. // Arguments: [off] -- number of bits to skip
  467. //
  468. // History: 28-Aug-92 BartoszM Created.
  469. //
  470. //----------------------------------------------------------------------------
  471. void CBitStream::SetPosition(ULONG off)
  472. {
  473. Win4Assert( off < SMARTBUF_PAGE_SIZE_IN_BITS );
  474. Win4Assert( !_buffer.isEmpty() );
  475. //ciDebugOut (( DEB_BITSTM, "SetPosition %d\n", off ));
  476. _pCurPos = _buffer.Get() + off / ULONG_BITS;
  477. _pEndBuf = _buffer.Get() + SMARTBUF_PAGE_SIZE_IN_DWORDS;
  478. _cbitLeftDW = ULONG_BITS - ( off - ULONG_BITS * ( off / ULONG_BITS ) );
  479. Win4Assert ( Position() == off );
  480. }
  481. //+---------------------------------------------------------------------------
  482. //
  483. // Member: CBitStream::CBitStream, public
  484. //
  485. // Synopsis: Copy Constructor (with pb as a clone of _pBuffer).
  486. //
  487. // Arguments: [pb] -- Pointer to memory for buffer.
  488. //
  489. // [orig] -- Original CBitStream to be copied.
  490. //
  491. // History: 13-Jan-92 AmyA Created.
  492. //
  493. //----------------------------------------------------------------------------
  494. CBitStream::CBitStream(CBitStream & orig)
  495. : _buffer(orig._buffer, orig._buffer.PageNum()),
  496. _cbitLeftDW(orig._cbitLeftDW),
  497. _oBuffer( 0 )
  498. {
  499. _pCurPos = _buffer.Get() + ( orig._pCurPos - orig._buffer.Get() );
  500. _pEndBuf = _buffer.Get() + SMARTBUF_PAGE_SIZE_IN_DWORDS;
  501. }
  502. //+---------------------------------------------------------------------------
  503. //
  504. // Member: CPBitStream::OverwriteBits, public
  505. //
  506. // Synopsis: Store bits in the buffer. This call doesn't affect
  507. // surrounding bits.
  508. //
  509. // Effects: OR the [cb] low bits in [ul] beginning at the 'bit-cursor'
  510. //
  511. // Arguments: [ul] -- A DWord containing data to store.
  512. //
  513. // [cb] -- The number of bits to store.
  514. //
  515. // History: 18-Jul-91 KyleP Created.
  516. // 02-Sep-92 BartoszM Rewrote for lazy paging
  517. //
  518. // Notes: Bits are stored 'big-endian'.
  519. //
  520. //----------------------------------------------------------------------------
  521. void CPBitStream::OverwriteBits(ULONG ul, unsigned cb)
  522. {
  523. ciDebugOut (( DEB_BITSTM , "OverwriteBits %d\n", cb ));
  524. Win4Assert(cb != 0 && cb <= ULONG_BITS);
  525. // Fault in the page if necessary
  526. if ( _buffer.isEmpty() || _buffer.PageNum() != _bitOff.Page())
  527. {
  528. _buffer.Refill(_bitOff.Page());
  529. }
  530. SetPosition(_bitOff.Offset());
  531. //
  532. // The easy case is the one where all the data fits in the current dword
  533. //
  534. if (cb <= _cbitLeftDW)
  535. {
  536. // this much will be left after current write
  537. _cbitLeftDW -= cb;
  538. // zero out a segment within current dword
  539. // first create a mask of cb bits by (ULONG_BITS - cb) shift right
  540. // then shift this mask left by the number of bits to be left
  541. *_pCurPos &= ~((0xFFFFFFFF >> (ULONG_BITS - cb)) << _cbitLeftDW);
  542. // shift ul left by the number of bits to be left
  543. *_pCurPos |= (ul << _cbitLeftDW);
  544. // prepare for the next write
  545. _bitOff += cb;
  546. Win4Assert( _bitOff.Offset() < SMARTBUF_PAGE_SIZE_IN_BITS );
  547. }
  548. else
  549. {
  550. IOverwriteBits( ul, cb );
  551. }
  552. }
  553. //+---------------------------------------------------------------------------
  554. //
  555. // Member: CWBitStream::IPutBits, private
  556. //
  557. // Synopsis: Store bits in the buffer. Internal version for multi-dword
  558. // case.
  559. //
  560. // Effects: Store the [cb] low bits in [ul] beginning at the 'bit-cursor'
  561. //
  562. // Arguments: [ul] -- A DWord containing data to store.
  563. //
  564. // [cb] -- The number of bits to store.
  565. //
  566. // History: 08-Jul-91 KyleP Created.
  567. //
  568. // Notes: Bits are stored 'big-endian'.
  569. //
  570. //----------------------------------------------------------------------------
  571. void CWBitStream::IPutBits(ULONG ul, unsigned cb)
  572. {
  573. Win4Assert ( cb > _cbitLeftDW );
  574. // ciDebugOut (( DEB_BITSTM, "IPutBits %d\n", cb ));
  575. if ( _cbitLeftDW != 0 )
  576. {
  577. Win4Assert ( _pCurPos < EndBuf() );
  578. //
  579. // Save the high portion in the current dword and save the
  580. // number of unwritten bits in cb
  581. //
  582. cb -= _cbitLeftDW;
  583. *_pCurPos |= (ul >> cb);
  584. }
  585. //
  586. // Increment to the next dword
  587. //
  588. NextDword();
  589. //
  590. // Store the remainder
  591. //
  592. _cbitLeftDW -= cb;
  593. *_pCurPos = ul << _cbitLeftDW;
  594. }
  595. //+---------------------------------------------------------------------------
  596. //
  597. // Member: CWBitStream::ZeroToEndOfPage, public
  598. //
  599. // Synopsis: Writes zeros from the current bit offset to ther end of the
  600. // page.
  601. //
  602. // History: 22-Apr-94 DwightKr Created.
  603. //
  604. // Notes: Bits are stored 'big-endian'.
  605. //
  606. //----------------------------------------------------------------------------
  607. void CWBitStream::ZeroToEndOfPage()
  608. {
  609. ULONG * pCurPos = _pCurPos;
  610. if ( (_cbitLeftDW != 0) && (_cbitLeftDW != 32) )
  611. {
  612. *pCurPos &= (0xFFFFFFFF << _cbitLeftDW);
  613. pCurPos++;
  614. }
  615. RtlZeroMemory( pCurPos, (EndBuf() - pCurPos) * sizeof(ULONG));
  616. }
  617. void CWBitStream::InitSignature()
  618. {
  619. _buffer.InitSignature();
  620. }
  621. //+---------------------------------------------------------------------------
  622. //
  623. // Member: CPBitStream::IOverwriteBits, private
  624. //
  625. // Synopsis: Store bits in the buffer. This call doesn't affect
  626. // surrounding bits.
  627. //
  628. // Effects: OR the [cb] low bits in [ul] beginning at the 'bit-cursor'
  629. //
  630. // Arguments: [ul] -- A DWord containing data to store.
  631. //
  632. // [cb] -- The number of bits to store.
  633. //
  634. // History: 18-Jul-91 KyleP Created.
  635. //
  636. // Notes: Bits are stored 'big-endian'.
  637. //
  638. //----------------------------------------------------------------------------
  639. void CPBitStream::IOverwriteBits(ULONG ul, unsigned cb)
  640. {
  641. Win4Assert ( cb > _cbitLeftDW );
  642. // prepare for next write
  643. _bitOff += cb;
  644. Win4Assert( _bitOff.Offset() < SMARTBUF_PAGE_SIZE_IN_BITS );
  645. if ( _cbitLeftDW > 0 )
  646. {
  647. Win4Assert ( _pCurPos < EndBuf() );
  648. // zero the remaining bits in the current dword
  649. *_pCurPos &= 0xFFFFFFFF << _cbitLeftDW;
  650. // this much will go to the next dword
  651. cb -= _cbitLeftDW;
  652. // shift away the part that goes to the next dword
  653. // and or in the rest
  654. *_pCurPos |= (ul >> cb);
  655. }
  656. //
  657. // Increment to the next dword
  658. //
  659. NextDword();
  660. //
  661. // Store the remainder
  662. //
  663. Win4Assert( cb <= ULONG_BITS );
  664. if ( cb == ULONG_BITS )
  665. {
  666. *_pCurPos = ul;
  667. }
  668. else
  669. {
  670. // zero the cb upper bits of the current dword
  671. *_pCurPos &= (0xFFFFFFFF >> cb);
  672. // fill them with cb bits from the bottom of ul
  673. *_pCurPos |= ul << (ULONG_BITS - cb);
  674. }
  675. }
  676. const ULONG g_aMasks[33] =
  677. {
  678. 0,
  679. 0x1,
  680. 0x3,
  681. 0x7,
  682. 0xf,
  683. 0x1f,
  684. 0x3f,
  685. 0x7f,
  686. 0xff,
  687. 0x1ff,
  688. 0x3ff,
  689. 0x7ff,
  690. 0xfff,
  691. 0x1fff,
  692. 0x3fff,
  693. 0x7fff,
  694. 0xffff,
  695. 0x1ffff,
  696. 0x3ffff,
  697. 0x7ffff,
  698. 0xfffff,
  699. 0x1fffff,
  700. 0x3fffff,
  701. 0x7fffff,
  702. 0xffffff,
  703. 0x1ffffff,
  704. 0x3ffffff,
  705. 0x7ffffff,
  706. 0xfffffff,
  707. 0x1fffffff,
  708. 0x3fffffff,
  709. 0x7fffffff,
  710. 0xffffffff,
  711. };
  712. //+---------------------------------------------------------------------------
  713. //
  714. // Member: CBitStream::IGetBits, public
  715. //
  716. // Synopsis: Retrieve bits from the buffer. Internal version for multi-
  717. // dword case.
  718. //
  719. // Arguments: [cb] -- Count of bits to retrieve.
  720. //
  721. // History: 12-Jul-91 KyleP Created.
  722. //
  723. //----------------------------------------------------------------------------
  724. ULONG CBitStream::IGetBits(unsigned cb)
  725. {
  726. Win4Assert ( cb > _cbitLeftDW );
  727. //ciDebugOut (( DEB_BITSTM, "IGetBits %d\n", cb ));
  728. //
  729. // Get the portion from the current DWord
  730. //
  731. ULONG ul;
  732. if ( 0 != _cbitLeftDW )
  733. {
  734. const ULONG mask = g_aMasks[ cb ];
  735. cb -= _cbitLeftDW;
  736. ul = (*_pCurPos << cb) & mask;
  737. }
  738. else
  739. ul = 0L;
  740. //
  741. // And the portion from the next.
  742. //
  743. NextDword();
  744. _cbitLeftDW -= cb;
  745. return ul | (*_pCurPos >> (ULONG_BITS - cb));
  746. } //IGetBits
  747. //+---------------------------------------------------------------------------
  748. //
  749. // Member: CWBitStream::PutBytes, public
  750. //
  751. // Synopsis: Store a number of bytes in the buffer.
  752. //
  753. // Arguments: [pb] -- Pointer to data to store.
  754. //
  755. // [cb] -- Number of bytes to store.
  756. //
  757. // History: 08-Jul-91 KyleP Created.
  758. //
  759. //----------------------------------------------------------------------------
  760. void CWBitStream::PutBytes(const BYTE * pb, unsigned cb)
  761. {
  762. // ciDebugOut (( DEB_BITSTM, "IPutBytes %d\n", cb ));
  763. while (cb > 0)
  764. {
  765. PutBits(*pb, 8);
  766. pb += 1;
  767. cb--;
  768. }
  769. }
  770. //+---------------------------------------------------------------------------
  771. //
  772. // Member: CBitStream::GetBytes, public
  773. //
  774. // Synopsis: Retrieve bytes from the buffer.
  775. //
  776. // Arguments: [pb] -- Pointer to area where data is returned.
  777. //
  778. // [cb] -- Count of bytes to retrieve.
  779. //
  780. // History: 12-Jul-91 KyleP Created.
  781. //
  782. //----------------------------------------------------------------------------
  783. void CBitStream::GetBytes(BYTE * pb, unsigned cb)
  784. {
  785. ciDebugOut (( DEB_BITSTM, "GetBytes %d\n", cb ));
  786. while (cb > 0)
  787. {
  788. *pb = BYTE ( GetBits(8) );
  789. pb++;
  790. cb--;
  791. }
  792. }
  793. //+---------------------------------------------------------------------------
  794. //
  795. // Member: CBitStream::Seek, public
  796. //
  797. // Synopsis: Seeks to the specified bit offset
  798. //
  799. // Arguments: [off] -- bit offset
  800. //
  801. // History: 28-Aug-92 BartoszM Created.
  802. //
  803. //----------------------------------------------------------------------------
  804. void CBitStream::Seek ( const BitOffset& off )
  805. {
  806. ciDebugOut (( DEB_BITSTM , "CBitStream::Seek %d:%d\n",
  807. off.Page(), off.Offset() ));
  808. if (_buffer.PageNum() != off.Page())
  809. {
  810. _buffer.Refill(off.Page());
  811. }
  812. SetPosition(off.Offset());
  813. }
  814. #if CIDBG == 1
  815. unsigned CBitStream::PeekBit()
  816. {
  817. if (_cbitLeftDW > 0)
  818. {
  819. ULONG ul = *_pCurPos;
  820. return( ul >> (_cbitLeftDW - 1)) & 1;
  821. }
  822. else
  823. {
  824. ULONG* pNewPos = _pCurPos + 1;
  825. if (pNewPos < EndBuf())
  826. {
  827. return(*pNewPos >> (ULONG_BITS-1));
  828. }
  829. else
  830. {
  831. Win4Assert ( 0 && "Untested" );
  832. CSmartBuffer bufTmp( _buffer, _buffer.PageNum() + 1 );
  833. ULONG* p = bufTmp.Get();
  834. unsigned bit = *p >> (ULONG_BITS-1);
  835. return(bit);
  836. }
  837. }
  838. }
  839. unsigned CPBitStream::PeekBit()
  840. {
  841. // Fault in the page if necessary
  842. if (_buffer.isEmpty() || _buffer.PageNum() != _bitOff.Page())
  843. _buffer.Refill(_bitOff.Page());
  844. SetPosition(_bitOff.Offset());
  845. return CBitStream::PeekBit();
  846. }
  847. void DumpDword ( ULONG* pul )
  848. {
  849. ULONG ul = *pul;
  850. for (int i = ULONG_BITS-1; i >= 0; i--)
  851. {
  852. ciDebugOut (( DEB_ITRACE | DEB_NOCOMPNAME,"%0d", (ul >> i) & 1 ));
  853. if (i %4 == 0)
  854. ciDebugOut (( DEB_ITRACE | DEB_NOCOMPNAME," " ));
  855. }
  856. ciDebugOut (( DEB_ITRACE | DEB_NOCOMPNAME,"\n" ));
  857. }
  858. void CBitStream::Dump()
  859. {
  860. ciDebugOut (( DEB_ITRACE, "CBitStream:\n"
  861. "\tpage %d\n"
  862. "\t_pCurPos 0x%x dwords from beginning\n"
  863. "\t_cbitLeftDW %d\n",
  864. _buffer.PageNum(), _pCurPos - _buffer.Get(), _cbitLeftDW ));
  865. if (_pCurPos > _buffer.Get())
  866. DumpDword ( _pCurPos - 1 );
  867. if (_pCurPos < EndBuf())
  868. {
  869. DumpDword ( _pCurPos );
  870. for (unsigned i = 1; i <= ULONG_BITS - _cbitLeftDW; i++ )
  871. {
  872. ciDebugOut (( DEB_ITRACE | DEB_NOCOMPNAME," " ));
  873. if (i %4 == 0)
  874. ciDebugOut (( DEB_ITRACE | DEB_NOCOMPNAME," " ));
  875. }
  876. ciDebugOut (( DEB_ITRACE | DEB_NOCOMPNAME,"^\n" ));
  877. }
  878. if (_pCurPos + 1 < EndBuf())
  879. DumpDword(_pCurPos + 1);
  880. }
  881. void CPBitStream::Dump()
  882. {
  883. // Fault in the page if necessary
  884. if (_buffer.isEmpty() || _buffer.PageNum() != _bitOff.Page())
  885. {
  886. _buffer.Refill(_bitOff.Page());
  887. }
  888. SetPosition(_bitOff.Offset());
  889. CBitStream::Dump();
  890. }
  891. #endif // CIDBG == 1