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.

2320 lines
62 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1991 - 2000.
  5. //
  6. // File: PComp.cxx
  7. //
  8. // Contents: Persistent index compressor, decompressor
  9. //
  10. // Classes: CCoder, CKeyComp, CPersComp
  11. //
  12. // History: 05-Jul-91 KyleP Created
  13. //
  14. //----------------------------------------------------------------------------
  15. #include <pch.cxx>
  16. #pragma hdrstop
  17. #pragma optimize( "t", on )
  18. #include "pcomp.hxx"
  19. #include "bitstm.hxx"
  20. const unsigned short NoKey = 0xffff;
  21. const unsigned OccCountBits = 3; // Bits to initially store for
  22. // an occurrence count.
  23. const unsigned cPidBits = 4;
  24. //+---------------------------------------------------------------------------
  25. //
  26. // Member: CCoder::CCoder, public
  27. //
  28. // Synopsis: Creates a coder
  29. //
  30. // Arguments: [widMax] -- The maximum workid in this index
  31. //
  32. // History: 05-Nov-91 BartoszM Created.
  33. //
  34. //----------------------------------------------------------------------------
  35. CCoder::CCoder ( WORKID widMax)
  36. :_widMaximum(widMax),
  37. _wid(0),
  38. _occ(0)
  39. {
  40. _key.SetCount(0);
  41. }
  42. //+---------------------------------------------------------------------------
  43. //
  44. // Member: CCoder::CCoder, public
  45. //
  46. // Synopsis: Creates a coder
  47. //
  48. // Arguments: [widMax] -- The maximum workid in this index
  49. // [keyInit] -- initial key
  50. //
  51. // History: 26-Aug-92 BartoszM Created.
  52. //
  53. //----------------------------------------------------------------------------
  54. CCoder::CCoder ( WORKID widMax, const CKeyBuf& keyInit)
  55. :_widMaximum(widMax),
  56. _wid(0),
  57. _occ(0),
  58. _key(keyInit)
  59. {
  60. }
  61. //+---------------------------------------------------------------------------
  62. //
  63. // Member: CCoder::CCoder, public
  64. //
  65. // Synopsis: Copy Constructor
  66. //
  67. // Arguments: [coder] -- The original CCoder that is being copied.
  68. //
  69. // History: 15-Jan-92 AmyA Created.
  70. //
  71. //----------------------------------------------------------------------------
  72. CCoder::CCoder ( CCoder &coder)
  73. :_key(coder._key),
  74. _widMaximum(coder._widMaximum),
  75. _wid(coder._wid),
  76. _occ(coder._occ),
  77. _cbitAverageWid(coder._cbitAverageWid)
  78. {
  79. }
  80. //+---------------------------------------------------------------------------
  81. //
  82. // Member: CCoder::~CCoder, public
  83. //
  84. // History: 05-Nov-91 BartoszM Created.
  85. //
  86. //----------------------------------------------------------------------------
  87. CCoder::~CCoder ( )
  88. {
  89. }
  90. //+---------------------------------------------------------------------------
  91. //
  92. // Member: CKeyComp::CKeyComp, public
  93. //
  94. // Synopsis: Creates a new (empty) key compressor.
  95. //
  96. // Arguments: [phIndex] -- physical index
  97. //
  98. // [widMax] -- The maximum workid which may be stored via
  99. // PutWorkId.
  100. //
  101. // History: 13-Nov-93 w-PatG Created.
  102. //
  103. //----------------------------------------------------------------------------
  104. CKeyComp::CKeyComp( CPhysIndex& phIndex,
  105. WORKID widMax,
  106. BOOL fUseLinks )
  107. : CCoder( widMax ),
  108. _sigKeyComp(eSigKeyComp),
  109. _phIndex(phIndex),
  110. _bitStream ( phIndex ),
  111. _fUseLinks( fUseLinks ),
  112. _bitStreamLink(phIndex),
  113. _fWriteFirstKeyFull(FALSE)
  114. {
  115. _bitOffCurKey.Init(0,0);
  116. _bitOffLastKey.Init(0,0);
  117. }
  118. //+---------------------------------------------------------------------------
  119. //
  120. // Function: CKeyComp
  121. //
  122. // Synopsis: Constructor used for creating a key compressor during a
  123. // restarted master merge. It has the ability to open an
  124. // existing index stream, seek to the specified point after
  125. // which new keys are to be added and zero-fill fromt the
  126. // starting point to the end of the page. Subsequent pages
  127. // are automatically zero-filled when they are loaded.
  128. //
  129. // Arguments: [phIndex] -- The physindex to which new keys are
  130. // going to be added
  131. // [widMax] -- Maximum wid in the index.
  132. // [bitoffRestart] -- BitOffset indicating where the new
  133. // keys will be added.
  134. // [bitoffSplitKey] -- BitOffset of the last key written
  135. // successfully to the disk completely. It is assumed that
  136. // there will be no need to even fix up the forward links.
  137. // [splitKey] -- The key which was written last.
  138. // [fUseLinks] -- Flag indicating if forward links should
  139. // be used or not.
  140. //
  141. // History: 4-10-94 srikants Created
  142. //
  143. // Notes:
  144. //
  145. //----------------------------------------------------------------------------
  146. CKeyComp::CKeyComp( CPhysIndex& phIndex,
  147. WORKID widMax,
  148. const BitOffset & bitoffRestart,
  149. const BitOffset & bitoffSplitKey,
  150. const CKeyBuf & splitKey,
  151. BOOL fUseLinks )
  152. : CCoder( widMax ),
  153. _sigKeyComp(eSigKeyComp),
  154. _phIndex(phIndex),
  155. _bitStream ( phIndex, bitoffRestart, FALSE ),
  156. _fUseLinks( fUseLinks ),
  157. _bitStreamLink(phIndex),
  158. _fWriteFirstKeyFull(FALSE)
  159. {
  160. //
  161. // Zero fill everything after the current position to the end of the
  162. // page.
  163. //
  164. ZeroToEndOfPage();
  165. // Write the signature
  166. InitSignature();
  167. _bitOffCurKey.Init(0,0);
  168. _bitOffLastKey.Init(0,0);
  169. //
  170. // Position to the place from where new keys must be written.
  171. //
  172. #if CIDBG == 1
  173. BitOffset bitOffCurr;
  174. GetOffset(bitOffCurr);
  175. Win4Assert( bitoffRestart.Page() == bitOffCurr.Page() &&
  176. bitoffRestart.Offset() == bitOffCurr.Offset() );
  177. // _bitStream.Seek(bitoffRestart);
  178. #endif // CIDBG
  179. //
  180. // If we are restarting and the split key is not the "MinKey"
  181. // then we must remember the split key as the "previous key".
  182. // If the split key is "MinKey", then we are starting from
  183. // beginning.
  184. //
  185. _key = splitKey;
  186. if ( _fUseLinks ) {
  187. //
  188. // Initialize the forward link tracker.
  189. //
  190. _bitStreamLink.Seek(bitoffSplitKey);
  191. }
  192. }
  193. //+---------------------------------------------------------------------------
  194. //
  195. // Member: CKeyComp::~CKeyComp, public
  196. //
  197. // Synopsis: Destroy a compressor/buffer pair.
  198. //
  199. // Effects: The main effect of destroying a compressor is that the
  200. // associated buffer is also destroyed (presumably storing
  201. // the data to a persistent medium).
  202. //
  203. // Signals: ???
  204. //
  205. // History: 05-Jul-91 KyleP Created.
  206. // 13-Nov-93 w-PatG Converted from CPersComp to CKeyComp
  207. //
  208. // Notes: Previous compressor is deleted in PutKey
  209. //
  210. //----------------------------------------------------------------------------
  211. CKeyComp::~CKeyComp()
  212. {
  213. ciDebugOut (( DEB_PCOMP,"CKeyComp::~CKeyComp() -- Last Key = %.*ws\n",
  214. _key.StrLen(), _key.GetStr() ));
  215. }
  216. //+---------------------------------------------------------------------------
  217. //
  218. // Member: CKeyComp::PutKey, public
  219. //
  220. // Synopsis: Starts recording data for a new key.
  221. //
  222. // Arguments: [key] -- The new key.
  223. //
  224. // [bitOff] -- (out) actual bit offset of the key in the index
  225. //
  226. // History: 05-Jul-91 KyleP Created.
  227. // 22-Nov-93 w-PatG Converted from CPersComp.
  228. //
  229. // Notes: The structure for each key is:
  230. // Prefix/Suffix size
  231. // Suffix
  232. // Property ID (Actually the key id)
  233. //
  234. //----------------------------------------------------------------------------
  235. void CKeyComp::PutKey(const CKeyBuf * pkey,
  236. BitOffset & bitOffCurKey)
  237. {
  238. //Debug message broken into two pieces due to use of static buffer
  239. ciDebugOut (( DEB_PCOMP | DEB_NOCOMPNAME,
  240. "\"%.*ws\"", pkey->StrLen(), pkey->GetStr() ));
  241. ciDebugOut (( DEB_PCOMP | DEB_NOCOMPNAME,
  242. " after \"%.*ws\"", _key.StrLen(), _key.GetStr() ));
  243. Win4Assert(pkey->Count() != 0 );
  244. Win4Assert((_key.Count() == 0) || Compare(&_key, pkey) < 0);
  245. Win4Assert(pkey->Pid() != pidAll);
  246. Win4Assert(pkey->Pid() != pidInvalid);
  247. // record the offset now.
  248. // for use by the directory
  249. _bitStream.GetOffset ( _bitOffCurKey );
  250. bitOffCurKey = _bitOffCurKey;
  251. if ( _fUseLinks )
  252. {
  253. // Get offset of previous key (the link stream is there)
  254. _bitStreamLink.GetOffset (_bitOffLastKey);
  255. // store the link data
  256. ULONG DeltaValue = bitOffCurKey.Delta(_bitOffLastKey);
  257. ciDebugOut (( 0x02000000, "@@@@ Delta : %lu @@@@\n", DeltaValue ));
  258. // check whether the size of whole persistent index exceed the maximum limit
  259. if ( DeltaValue >= LINK_MAX_VALUE ) {
  260. ciDebugOut (( 0x01000000 | DEB_PCOMP | DEB_NOCOMPNAME,
  261. "\n@@@@ Key : \"%.*ws\" Exceed the MAX SIZE : %lu\n",
  262. _key.StrLen(), _key.GetStr(), DeltaValue ));
  263. DeltaValue = 0;
  264. }
  265. _bitStreamLink.OverwriteBits( DeltaValue, LINK_MAX_BITS );
  266. // reposition the link stream
  267. _bitStreamLink.Seek ( bitOffCurKey );
  268. // save space for the link
  269. _bitStream.PutBits ( 0, LINK_MAX_BITS );
  270. }
  271. //
  272. // If we need to write the FIRST key on each page in its entirety,
  273. // and we have crossed a page boundary, then set the prefix to 0,
  274. // which forces the key to be written in its entirety.
  275. //
  276. unsigned cPrefix = 0;
  277. if ( _fWriteFirstKeyFull &&
  278. ( _bitOffCurKey.Page() != _bitOffLastKey.Page()) )
  279. {
  280. //
  281. // If we're not using links, then we haven't been tracking the
  282. // bit offset of the last key. Do it here.
  283. //
  284. if ( !_fUseLinks )
  285. {
  286. _bitOffLastKey = _bitOffCurKey;
  287. }
  288. }
  289. else
  290. {
  291. unsigned mincb = __min(_key.Count(), pkey->Count());
  292. for (cPrefix = 0; cPrefix < mincb; cPrefix++)
  293. if ((_key.GetBuf())[cPrefix] != (pkey->GetBuf())[cPrefix])
  294. break;
  295. }
  296. unsigned cSuffix = pkey->Count() - cPrefix;
  297. PutPSSize ( cPrefix, cSuffix );
  298. //
  299. // Store the suffix.
  300. //
  301. _bitStream.PutBytes( pkey->GetBuf() + cPrefix, cSuffix);
  302. PutPid ( pkey->Pid() );
  303. //
  304. // Copy the piece of key that changed.
  305. //
  306. memcpy(_key.GetWritableBuf() + cPrefix, pkey->GetBuf() + cPrefix, cSuffix);
  307. _key.SetCount( pkey->Count() );
  308. _key.SetPid ( pkey->Pid() );
  309. }
  310. //+---------------------------------------------------------------------------
  311. //
  312. // Member: CKeyComp::IBitCompress, private
  313. //
  314. // Synopsis: Compress and store a number.
  315. //
  316. // Arguments: [ul] -- Number to store.
  317. //
  318. // [cbitAverage] -- Minimum number of bits to store.
  319. //
  320. // Algorithm: First, store the bottom cbitAverage bits.
  321. // while there are more bits to store
  322. // store a 1 bit indicating more to follow
  323. // store the next n bits, where n = 2, 3, 4, ...
  324. // store a 0 bit indicating end of sequence
  325. //
  326. // History: 08-Jul-91 KyleP Created.
  327. // 06-Dec-93 w-PatG Moved from CPersComp.
  328. //
  329. //----------------------------------------------------------------------------
  330. void CKeyComp::IBitCompress(ULONG ul, unsigned cbitAverage, unsigned bitSize)
  331. {
  332. //
  333. // Figure out the size of the 'hole' after the last bits are
  334. // written out and add 0 bits at the high end so that the
  335. // last putbits really stores exactly the remaining bits.
  336. // (Right pad the number)
  337. //
  338. int cbitToStore;
  339. int cbitPadding = (int)(bitSize - cbitAverage);
  340. for (cbitToStore = 2; cbitPadding > 0; cbitToStore++)
  341. cbitPadding -= cbitToStore;
  342. Win4Assert(cbitPadding >= -cbitToStore);
  343. cbitPadding = -cbitPadding;
  344. bitSize += cbitPadding;
  345. //
  346. // Store the bits a dword at a time for efficiency. They are kept
  347. // in ultmp until they are stored. cbitTmp is the count of valid bits
  348. // in ulTmp. ibitValid is the highest unstored bit.
  349. //
  350. int ibitValid;
  351. ULONG ulTmp;
  352. unsigned cbitTmp;
  353. ibitValid = bitSize;
  354. Win4Assert( (ibitValid - cbitAverage) < ULONG_BITS );
  355. ulTmp = ul >> (ibitValid - cbitAverage);
  356. cbitTmp = cbitAverage;
  357. ibitValid -= cbitAverage;
  358. bitSize -= cbitAverage;
  359. //
  360. // Now store the cbitAverage bits and the
  361. // remaining bits, 2, 3, 4, ... at a time
  362. //
  363. for (cbitToStore = 2; ibitValid > 0; cbitToStore++)
  364. {
  365. //
  366. // If there isn't enough space left in the DWord, then
  367. // write it out and start a new one.
  368. //
  369. if (cbitTmp + cbitToStore + 1 > ULONG_BITS)
  370. {
  371. _bitStream.PutBits(ulTmp, cbitTmp);
  372. ulTmp = 0;
  373. cbitTmp = 0;
  374. }
  375. //
  376. // Store a continuation bit
  377. //
  378. ulTmp = (ulTmp << 1) | 1;
  379. cbitTmp++;
  380. //
  381. // Store the next top 2, 3, ... bits
  382. //
  383. Win4Assert( cbitToStore < ULONG_BITS );
  384. Win4Assert( (ibitValid - cbitToStore) < ULONG_BITS );
  385. ulTmp = (ulTmp << cbitToStore) |
  386. (ul >> (ibitValid - cbitToStore)) &
  387. ~(0xffffffffL << cbitToStore);
  388. ibitValid -= cbitToStore;
  389. cbitTmp += cbitToStore;
  390. Win4Assert(ibitValid >= 0); // Loop should terminate w/
  391. // ibitValid == 0
  392. }
  393. //
  394. // Write out the final termination bit (0).
  395. //
  396. if (cbitTmp == ULONG_BITS)
  397. {
  398. _bitStream.PutBits(ulTmp, cbitTmp);
  399. ulTmp = 0;
  400. cbitTmp = 0;
  401. }
  402. ulTmp <<= 1;
  403. _bitStream.PutBits(ulTmp, cbitTmp + 1);
  404. }
  405. //+---------------------------------------------------------------------------
  406. //
  407. // Member: CKeyComp::PutPSSize, private
  408. //
  409. // Synopsis: Writes key prefix and suffix sizes
  410. //
  411. // Arguments: [cPrefix] -- size of prefix
  412. // [cSuffix] -- size of suffix
  413. //
  414. // History: 06-Nov-91 BartoszM Created.
  415. // 22-Nov-93 w-PatG Moved from CPersComp to CKeyComp
  416. //
  417. // Notes:
  418. // Store the prefix/suffix size followed by the suffix. If both
  419. // the prefix and suffix fit in 4 bits each then store each as
  420. // 4 bits, else store a 0 byte followed by a 8 bits each for
  421. // prefix and suffix.
  422. //
  423. //----------------------------------------------------------------------------
  424. inline void CKeyComp::PutPSSize ( unsigned cPrefix, unsigned cSuffix )
  425. {
  426. Win4Assert ( cPrefix + cSuffix != 0 );
  427. ciDebugOut (( DEB_PCOMP | DEB_NOCOMPNAME,
  428. "\n(%d:%d) ", cPrefix, cSuffix ));
  429. if ((cPrefix <= 0xF) && (cSuffix <= 0xF))
  430. {
  431. _bitStream.PutBits((cPrefix << 4) | cSuffix, 8);
  432. }
  433. else
  434. {
  435. Win4Assert((cPrefix < 256) && (cSuffix < 256));
  436. Win4Assert(cPrefix + cSuffix <= MAXKEYSIZE );
  437. _bitStream.PutBits((cPrefix << 8) | cSuffix, 8 + 16);
  438. }
  439. }
  440. //+---------------------------------------------------------------------------
  441. //
  442. // Member: CKeyComp::PutPid, private
  443. //
  444. // Synopsis: Writes Property ID
  445. //
  446. // Arguments: [pid] -- property id
  447. //
  448. // History: 06-Nov-91 BartoszM Created.
  449. // 22-Nov-93 w-PatG Moved from CPersComp to CKeyComp
  450. //
  451. //----------------------------------------------------------------------------
  452. inline void CKeyComp::PutPid ( PROPID pid )
  453. {
  454. //
  455. // Just store a 0 bit if contents, else
  456. // a 1 followed by ULONG propid.
  457. //
  458. if ( pid == pidContents)
  459. {
  460. _bitStream.PutBits(0, 1);
  461. }
  462. else
  463. {
  464. ciDebugOut (( DEB_PCOMP | DEB_NOCOMPNAME,
  465. " =PID %d= ", pid ));
  466. _bitStream.PutBits(1, 1);
  467. BitCompress ( pid, cPidBits );
  468. }
  469. }
  470. //+---------------------------------------------------------------------------
  471. //
  472. // Member: CKeyDeComp::CKeyDeComp, public
  473. //
  474. // Synopsis: Creates a new persistent decompressor
  475. // at the beginning of an index
  476. //
  477. // Arguments: [iid] -- index id
  478. // [phIndex] -- physical index
  479. // [widMax] -- Maximum workid which may be in the buffer.
  480. // This must be the same number was was used
  481. // during compression.
  482. //
  483. // History: 12-Jul-91 KyleP Created.
  484. // 21-Apr-92 BartoszM Split into two constructors
  485. // 30-Nov-93 w-PatG Converted from CPersDeComp
  486. // 10-Apr-94 SrikantS Adapted to not use the directory
  487. // because it may not exist during a
  488. // restarted master merge.
  489. //
  490. // Notes: Some of the arguments passed in may later be deemed to be
  491. // unnecessary. Some may be converted to different purposes at a
  492. // later date.
  493. //----------------------------------------------------------------------------
  494. CKeyDeComp::CKeyDeComp( PDirectory& pDir,
  495. INDEXID iid,
  496. CPhysIndex& phIndex,
  497. WORKID widMax,
  498. BOOL fUseLinks,
  499. BOOL fUseDir )
  500. : CCoder ( widMax ),
  501. CKeyCursor (iid, widMax),
  502. _sigKeyDeComp(eSigKeyDeComp),
  503. _bitStream ( phIndex ),
  504. _fUseLinks( fUseLinks ),
  505. _pDir( pDir ),
  506. _fUseDir( fUseDir ),
  507. _fAtSentinel( FALSE ),
  508. _physIndex ( phIndex )
  509. #if (CIDBG == 1)
  510. ,_fLastKeyFromDir( FALSE )
  511. #endif
  512. {
  513. LoadKey();
  514. }
  515. //+---------------------------------------------------------------------------
  516. //
  517. // Member: CKeyDeComp::CKeyDeComp, public
  518. //
  519. // Synopsis: Creates a new persistent decompressor.
  520. // positioned at a specified key
  521. //
  522. // Arguments: [iid] -- index id
  523. // [phIndex] -- physical index
  524. // [keyPos] -- bit offset to key stored in directory
  525. // [keyInit] -- initial key
  526. // [pKey] -- actual key to search for
  527. // [widMax] -- Maximum workid which may be in the buffer.
  528. // This must be the same number was was used
  529. // during compression.
  530. //
  531. // History: 12-Jul-91 KyleP Created.
  532. // 21-Apr-92 BartoszM Split into two constructors
  533. // 30-Nov-93 w-PatG Converted from CPersDeComp
  534. //
  535. //----------------------------------------------------------------------------
  536. CKeyDeComp::CKeyDeComp( PDirectory& pDir,
  537. INDEXID iid,
  538. CPhysIndex& phIndex,
  539. BitOffset& keyPos,
  540. const CKeyBuf& keyInit,
  541. const CKey* pKey,
  542. WORKID widMax,
  543. BOOL fUseLinks,
  544. BOOL fUseDir )
  545. : CCoder ( widMax, keyInit ),
  546. CKeyCursor (iid, widMax),
  547. _sigKeyDeComp(eSigKeyDeComp),
  548. _bitStream( phIndex, keyPos ),
  549. _fUseLinks( fUseLinks ),
  550. _pDir( pDir ),
  551. _fUseDir( fUseDir ),
  552. _fAtSentinel( FALSE ),
  553. _physIndex ( phIndex )
  554. #if (CIDBG == 1)
  555. ,_fLastKeyFromDir( FALSE )
  556. #endif
  557. {
  558. Win4Assert(pKey);
  559. LoadKey();
  560. SeekKey( pKey);
  561. }
  562. //+---------------------------------------------------------------------------
  563. //
  564. // Member: CKeyDeComp::CKeyDeComp, public
  565. //
  566. // Synopsis: Copy Constructor
  567. //
  568. // Effects: Copies most of the values in decomp. Calls copy constructor
  569. // for CCoder.
  570. //
  571. // Arguments: [decomp] -- Original CKeyDeComp to be copied.
  572. //
  573. // History: 08-Jan-92 AmyA Created.
  574. // 07-Dec-93 w-PatG Stole from CPersDeComp.
  575. //
  576. //----------------------------------------------------------------------------
  577. CKeyDeComp::CKeyDeComp(CKeyDeComp & decomp)
  578. : CCoder (decomp),
  579. CKeyCursor(decomp),
  580. _sigKeyDeComp(eSigKeyDeComp),
  581. _bitStream(decomp._bitStream),
  582. _fUseLinks( decomp._fUseLinks ),
  583. _bitOffNextKey(decomp._bitOffNextKey),
  584. _pDir( decomp._pDir ),
  585. _fUseDir( decomp._fUseDir ),
  586. _fAtSentinel( decomp._fAtSentinel ),
  587. _physIndex(decomp._physIndex)
  588. #if (CIDBG == 1)
  589. ,_fLastKeyFromDir( decomp._fLastKeyFromDir )
  590. #endif
  591. {
  592. }
  593. //+---------------------------------------------------------------------------
  594. //
  595. // Member: CKeyDeComp::~CKeyDeComp, public
  596. //
  597. // Synopsis: Destroy a decompressor/buffer pair.
  598. //
  599. // Effects: The main effect of destroying a decompressor is that the
  600. // associated buffer is also destroyed (presumably storing
  601. // the data to a persistent medium).
  602. //
  603. // Signals: ???
  604. //
  605. // History: 30-Nov-93 w-PatG Created.
  606. //
  607. //----------------------------------------------------------------------------
  608. CKeyDeComp::~CKeyDeComp()
  609. {}
  610. //+---------------------------------------------------------------------------
  611. //
  612. // Member: CKeyDeComp::GetKey, public
  613. //
  614. // Synopsis: Retrieves the current key.
  615. //
  616. // Returns: A pointer to the current key. If at the end of page or
  617. // end of index, returns null.
  618. //
  619. // History: 15-Jul-91 KyleP Created.
  620. // 30-Nov-93 w-PatG Moved from CPersDeComp.
  621. //
  622. //----------------------------------------------------------------------------
  623. const CKeyBuf * CKeyDeComp::GetKey( BitOffset * pBitOff )
  624. {
  625. if ( IsAtSentinel() )
  626. return(0);
  627. if ( pBitOff )
  628. GetOffset( *pBitOff );
  629. return(&_key);
  630. }
  631. const CKeyBuf * CKeyDeComp::GetKey()
  632. {
  633. if ( IsAtSentinel() )
  634. return(0);
  635. return(&_key);
  636. }
  637. //+---------------------------------------------------------------------------
  638. //
  639. // Member: CKeyDeComp::GetNextKey, public
  640. //
  641. // Synopsis: Retrieve the next key from the content index.
  642. //
  643. // Arguments: [pBitOff] -- optional, will have the offset of the beginning
  644. // of the key.
  645. //
  646. // Returns: A pointer to the key, or 0 if end of page/index reached.
  647. //
  648. // History: 15-Jul-91 KyleP Created.
  649. // 30-Nov-93 w-PatG Converted from CPersDeComp.
  650. // 10-Apr-94 SrikantS Added pBitOff as an optional param.
  651. //
  652. //----------------------------------------------------------------------------
  653. const CKeyBuf * CKeyDeComp::GetNextKey( BitOffset * pBitOff )
  654. {
  655. if ( _fUseLinks )
  656. {
  657. if ( !_bitOffNextKey.Valid() )
  658. {
  659. Win4Assert( _fUseDir );
  660. _pDir.SeekNext( _key, 0, _bitOffNextKey );
  661. Win4Assert( _bitOffNextKey.Valid() );
  662. ciDebugOut (( 0x01000000 | DEB_PCOMP | DEB_NOCOMPNAME, "*** Result : Page %lu OffSet %lu\n",
  663. _bitOffNextKey.Page(), _bitOffNextKey.Offset() ));
  664. #if (CIDBG == 1)
  665. _fLastKeyFromDir = TRUE;
  666. #endif // CIDBG == 1
  667. }
  668. _bitStream.Seek ( _bitOffNextKey );
  669. }
  670. if ( pBitOff )
  671. {
  672. _bitStream.GetOffset( *pBitOff );
  673. }
  674. LoadKey();
  675. const CKeyBuf * pkey = GetKey();
  676. return(pkey);
  677. }
  678. const CKeyBuf * CKeyDeComp::GetNextKey()
  679. {
  680. return GetNextKey( 0 );
  681. }
  682. void CKeyDeComp::GetOffset( BitOffset & bitOff )
  683. {
  684. _bitStream.GetOffset( bitOff );
  685. }
  686. //+---------------------------------------------------------------------------
  687. //
  688. // Member: CKeyDeComp::SeekKey, private
  689. //
  690. // Synopsis: Seek in the decompressor
  691. //
  692. // Arguments: [pkey] -- Key to search for.
  693. //
  694. // [op] -- Seek equality operation (EQ, GE, etc.)
  695. //
  696. // Returns: A pointer to the key to cursor is actually on. This may
  697. // be = or > [pkey].
  698. //
  699. // History: 26-Apr-91 KyleP Created.
  700. // 25-Aug-92 BartoszM Moved to CPersDecomp
  701. // 30-Nov-93 w-PatG Moved to CKeyDeComp
  702. //
  703. //----------------------------------------------------------------------------
  704. const CKeyBuf * CKeyDeComp::SeekKey(const CKey * pKeySearch)
  705. {
  706. //
  707. // Find the key >= the specified key.
  708. //
  709. const CKeyBuf* pKeyFound = GetKey();
  710. while (pKeyFound != 0)
  711. {
  712. //----------------------------------------------------
  713. // Notice: Make sure that pidAll is smaller
  714. // than any other legal PID. If the search key
  715. // has pidAll we want to be positioned at the beginning
  716. // of the range.
  717. //----------------------------------------------------
  718. Win4Assert ( pidAll == 0 );
  719. // skip keys less than the search key
  720. if ( pKeySearch->Compare(*pKeyFound) > 0)
  721. {
  722. pKeyFound = GetNextKey();
  723. }
  724. else
  725. break;
  726. }
  727. return(pKeyFound);
  728. }
  729. void CPersDeComp::RatioFinished (ULONG& denom, ULONG& num)
  730. {
  731. denom = _cWid;
  732. Win4Assert ( _cWid >= _cWidLeft );
  733. num = _cWid - _cWidLeft;
  734. }
  735. //+---------------------------------------------------------------------------
  736. //
  737. // Member: CKeyDeComp::BitUnCompress, private
  738. //
  739. // Synopsis: Uncompress a number
  740. //
  741. // Arguments: [cbitAverage] -- Minimum number of bits to store.
  742. //
  743. // History: 15-Jul-91 KyleP Created.
  744. //
  745. //----------------------------------------------------------------------------
  746. __forceinline ULONG CKeyDeComp::BitUnCompress( unsigned cbitAverage)
  747. {
  748. //
  749. // Get the initial count plus a stop bit.
  750. //
  751. Win4Assert( cbitAverage < ULONG_BITS );
  752. ULONG ul = _bitStream.GetBits(cbitAverage + 1);
  753. //
  754. // Simple case: The number fits in the original cbitAverage bits
  755. // (e.g. the stop bit is 0).
  756. // No additional processing necessary.
  757. //
  758. // Complex: Retrieve additional components.
  759. //
  760. if ((ul & 1) == 0)
  761. return(ul >> 1);
  762. return IBitUnCompress ( cbitAverage, ul );
  763. }
  764. //+---------------------------------------------------------------------------
  765. //
  766. // Member: CKeyDeComp::IBitUnCompress, private
  767. //
  768. // Synopsis: Uncompress a number
  769. //
  770. // Arguments: [cbitAverage] -- Minimum number of bits to store.
  771. //
  772. // History: 15-Jul-91 KyleP Created.
  773. // 06-Dec-93 w-PatG Moved from CPersDeComp.
  774. //
  775. //----------------------------------------------------------------------------
  776. ULONG CKeyDeComp::IBitUnCompress( unsigned cbitAverage, ULONG ul)
  777. {
  778. Win4Assert ( ul & 1 );
  779. int BitsToGetPlus1 = 3;
  780. do
  781. {
  782. //
  783. // Kill the stop bit.
  784. //
  785. ul >>= 1;
  786. //
  787. // Get the next component and its stop bit.
  788. //
  789. ULONG ulPartial = _bitStream.GetBits(BitsToGetPlus1);
  790. Win4Assert( BitsToGetPlus1 < ULONG_BITS );
  791. ul = (ul << BitsToGetPlus1) | ulPartial;
  792. BitsToGetPlus1++;
  793. }
  794. while (ul & 1);
  795. ul >>= 1;
  796. return(ul);
  797. }
  798. //+---------------------------------------------------------------------------
  799. //
  800. // Member: CKeyDeComp::LoadKey, private
  801. //
  802. // Synopsis: Loads data for the next key.
  803. //
  804. // Effects: Reads a key from the current position in _bitStream and
  805. // sets per key state.
  806. //
  807. // Signals: ???
  808. //
  809. // History: 12-Jul-91 KyleP Created.
  810. // 06-Dec-93 w-PatG Modified from CPersDeComp.
  811. //
  812. //----------------------------------------------------------------------------
  813. void CKeyDeComp::LoadKey()
  814. {
  815. ULONG TmpValue;
  816. if ( _fUseLinks )
  817. {
  818. _bitStream.GetOffset ( _bitOffNextKey );
  819. TmpValue = _bitStream.GetBits ( LINK_MAX_BITS );
  820. }
  821. //
  822. // Retrieve the prefix/suffix. Assume they are stored in 4 bits each
  823. // first.
  824. //
  825. unsigned cPrefix, cSuffix;
  826. LoadPSSize ( cPrefix, cSuffix );
  827. //
  828. // Load the key itself.
  829. //
  830. #if CIDBG == 1
  831. if ( _fLastKeyFromDir )
  832. {
  833. //
  834. // We know what the key should be. Compute prefix and
  835. // suffix. Make sure they match.
  836. //
  837. unsigned mincb = __min( _key.Count(), _pDir.GetLastKey().Count() );
  838. for (unsigned cOldPrefix = 0; cOldPrefix < mincb; cOldPrefix++)
  839. {
  840. if ( (_key.GetBuf())[cOldPrefix] !=
  841. (_pDir.GetLastKey().GetBuf())[cOldPrefix] )
  842. break;
  843. }
  844. unsigned cOldSuffix = _pDir.GetLastKey().Count() - cOldPrefix;
  845. if ( (0 != cPrefix) && (cPrefix != cOldPrefix || cSuffix != cOldSuffix) )
  846. {
  847. ciDebugOut(( DEB_ERROR, "Corrupt index or directory!\n" ));
  848. ciDebugOut(( DEB_ERROR, "From index: cPrefix = %d, cSuffix = %d\n",
  849. cPrefix, cSuffix ));
  850. ciDebugOut(( DEB_ERROR, "From directory: cPrefix = %d, cSuffix = %d\n",
  851. cOldPrefix, cOldSuffix ));
  852. Win4Assert( !"Corrupt index or directory" );
  853. }
  854. _fLastKeyFromDir = FALSE;
  855. }
  856. #endif // CIDBG == 1
  857. if ( 0 == ( cPrefix + cSuffix ) )
  858. {
  859. //
  860. // Disabled asserts prior to widespread Query rollout in NT 5, so
  861. // that the general NT user is not bothered by this asserts.
  862. //
  863. //Win4Assert ( "Data corruption" && cPrefix + cSuffix != 0 );
  864. PStorage & storage = _physIndex.GetStorage();
  865. storage.ReportCorruptComponent( L"KeyDecompressor1" );
  866. THROW( CException( CI_CORRUPT_DATABASE) );
  867. }
  868. if ( cPrefix > _key.Count() )
  869. {
  870. //
  871. // Disabled asserts prior to widespread Query rollout in NT 5, so
  872. // that the general NT user is not bothered by this asserts.
  873. //
  874. //Win4Assert ( "Data corruption" && cPrefix <= _key.Count() );
  875. PStorage & storage = _physIndex.GetStorage();
  876. storage.ReportCorruptComponent( L"KeyDecompressor2" );
  877. THROW( CException( CI_CORRUPT_DATABASE) );
  878. }
  879. _bitStream.GetBytes(_key.GetWritableBuf() + cPrefix, cSuffix);
  880. _key.SetCount( cPrefix + cSuffix );
  881. if ( _key.IsMaxKey() )
  882. {
  883. ciDebugOut (( DEB_ITRACE, "\n<<Sentinel key>>\n" ));
  884. _fAtSentinel = TRUE;
  885. return;
  886. }
  887. #if CIDBG == 1
  888. //
  889. // This it to test the directory-index interaction when things go wrong. Don't delete
  890. // this code before talking with Dwight/SrikantS/KyleP.
  891. //
  892. #if 0
  893. {
  894. iidDebug = 0x10002; // Looking for this index
  895. WCHAR wcsDebugKey[] = L"TRUE"; // Looking for this key
  896. unsigned lenDebug = min( wcslen( wcsDebugKey ), _key.StrLen() );
  897. //
  898. // If the key we are looking for is found in the desired index, break and
  899. // step through the code to see what is going on.
  900. //
  901. if ( iidDebug == _iid && 0 == _wcsnicmp( _key.GetStr(), wcsDebugKey , lenDebug ) )
  902. {
  903. Win4Assert( !"Only during baby-sitting mode" );
  904. }
  905. }
  906. #endif // 1
  907. #endif // CIDBG==1
  908. //
  909. // Load the property ID.
  910. //
  911. //
  912. // Store a 0 bit if contents, else
  913. // a 1 followed by ULONG propid.
  914. //
  915. ciDebugOut (( DEB_PCOMP | DEB_NOCOMPNAME,
  916. "\"%.*ws\" ", _key.StrLen(),_key.GetStr()));
  917. LoadPid();
  918. // continue to set _bitOffNextKey
  919. if ( _fUseLinks )
  920. {
  921. if ( TmpValue == 0 )
  922. {
  923. // the size of the current index must exceed the
  924. // max. limit. Use CI Directory to search the next key
  925. // position
  926. ciDebugOut (( 0x01000000, "\n*** Key : \"%.*ws\"\n",_key.StrLen(), _key.GetStr() ));
  927. ciDebugOut (( 0x01000000 | DEB_PCOMP | DEB_NOCOMPNAME, "\n\t*** Start search next key's offset\n" ));
  928. _bitOffNextKey.SetInvalid();
  929. }
  930. else
  931. {
  932. _bitOffNextKey += TmpValue;
  933. ciDebugOut (( DEB_PCOMP | DEB_NOCOMPNAME, "\n\t$$$ Next key : Page %lu OffSet %lu\n",
  934. _bitOffNextKey.Page(), _bitOffNextKey.Offset() ));
  935. }
  936. }
  937. }
  938. //+---------------------------------------------------------------------------
  939. //
  940. // Member: CKeyDeComp::LoadPSSize, private
  941. //
  942. // Synopsis: Load key prefix and suffix sizes
  943. //
  944. // Arguments: [cPrefix] -- (return) prefix size
  945. // [cSuffix] -- (return) suffix size
  946. //
  947. // History: 05-Nov-91 BartoszM Created.
  948. // 30-Nov-93 w-PatG Moved from CPersDeComp.
  949. //
  950. //----------------------------------------------------------------------------
  951. inline void CKeyDeComp::LoadPSSize ( unsigned& cPrefix, unsigned& cSuffix )
  952. {
  953. ULONG ul = _bitStream.GetBits(8);
  954. if (ul != 0) // 4 bits for prefix and suffix
  955. {
  956. cPrefix = (unsigned)ul >> 4;
  957. cSuffix = (unsigned)ul & 0xF;
  958. }
  959. else // 8 bits for prefix and suffix
  960. {
  961. ul = _bitStream.GetBits(16);
  962. cPrefix = (unsigned)ul >> 8;
  963. cSuffix = (unsigned)ul & 0xFF;
  964. }
  965. Win4Assert(cPrefix + cSuffix <= MAXKEYSIZE );
  966. ciDebugOut (( DEB_PCOMP | DEB_NOCOMPNAME,
  967. "\n(%d:%d) ", cPrefix, cSuffix));
  968. }
  969. //+---------------------------------------------------------------------------
  970. //
  971. // Member: CKeyDeComp::LoadPid, private
  972. //
  973. // Synopsis: Load property id
  974. //
  975. // History: 05-Nov-91 BartoszM Created.
  976. // 06-Dec-93 w-PatG Moved from CPersDeComp.
  977. //
  978. // Notes: The Property id is used for different purposes in CKeyDeComp
  979. // and CPersDeComp. In CKeyDeComp, a PROPID is actually a key id.
  980. //
  981. //----------------------------------------------------------------------------
  982. __forceinline void CKeyDeComp::LoadPid ()
  983. {
  984. ULONG ul = _bitStream.GetBits(1);
  985. if (ul == 0)
  986. {
  987. _key.SetPid(pidContents);
  988. }
  989. else
  990. {
  991. ul = BitUnCompress ( cPidBits );
  992. _key.SetPid (ul);
  993. }
  994. #if CIDBG == 1
  995. if (ul != 0)
  996. ciDebugOut (( DEB_PCOMP | DEB_NOCOMPNAME," =PID %d= ", ul ));
  997. #endif
  998. }
  999. //
  1000. // Unused, but required for inheritance.
  1001. //
  1002. OCCURRENCE CKeyDeComp::Occurrence()
  1003. {
  1004. Win4Assert( !"CKeyDeComp::Occurrence() -- invalid call" );
  1005. return( 0 );
  1006. }
  1007. OCCURRENCE CKeyDeComp::NextOccurrence()
  1008. {
  1009. Win4Assert( !"CKeyDeComp::NextOccurrence() -- invalid call" );
  1010. return( 0 );
  1011. }
  1012. ULONG CKeyDeComp::OccurrenceCount()
  1013. {
  1014. Win4Assert( !"CKeyDeComp::OccurrenceCount() -- invalid call" );
  1015. return( 0 );
  1016. }
  1017. OCCURRENCE CKeyDeComp::MaxOccurrence()
  1018. {
  1019. Win4Assert( !"CKeyDeComp::MaxOccurrence() -- invalid call" );
  1020. return( 1 );
  1021. }
  1022. WORKID CKeyDeComp::WorkId()
  1023. {
  1024. Win4Assert( !"CKeyDeComp::WorkId() -- invalid call" );
  1025. return( 0 );
  1026. }
  1027. WORKID CKeyDeComp::NextWorkId()
  1028. {
  1029. Win4Assert( !"CKeyDeComp::NextWorkId() -- invalid call" );
  1030. return( 0 );
  1031. }
  1032. ULONG CKeyDeComp::HitCount()
  1033. {
  1034. Win4Assert( !"CKeyDeComp::HitCount() -- invalid call" );
  1035. return(0);
  1036. }
  1037. //+---------------------------------------------------------------------------
  1038. //
  1039. // Member: CPersComp::CPersComp, public
  1040. //
  1041. // Synopsis: Creates a new (empty) persistent compressor.
  1042. //
  1043. // Arguments: [phIndex] -- physical index
  1044. //
  1045. // [widMax] -- The maximum workid which may be stored via
  1046. // PutWorkId.
  1047. //
  1048. // History: 05-Jul-91 KyleP Created.
  1049. //
  1050. //----------------------------------------------------------------------------
  1051. CPersComp::CPersComp(
  1052. CPhysIndex& phIndex,
  1053. WORKID widMax)
  1054. : CKeyComp( phIndex, widMax ),
  1055. _sigPersComp(eSigPersComp),
  1056. _cWidProposed(0),
  1057. _cWidActual(0),
  1058. _bitStreamPatch ( phIndex )
  1059. {
  1060. #if CIDBG == 1
  1061. _cOccLeft = 0;
  1062. #endif // CIDBG == 1
  1063. }
  1064. //+---------------------------------------------------------------------------
  1065. //
  1066. // Function: CPersComp::CPersComp
  1067. //
  1068. // Synopsis: Constructor for the persistent compressor capable of dealing
  1069. // with a partially constructed index stream during a restarted
  1070. // master merge.
  1071. //
  1072. // Arguments: [phIndex] -- The physical index being constructed
  1073. // during a restarted master merge.
  1074. // [widMax] -- Maximum wid for the index.
  1075. // [bitOffRestart] -- Offset where to restart adding new
  1076. // keys.
  1077. // [bitOffSplitKey] -- Beginning offset of the last key added.
  1078. // If no keys added, set to 0,0.
  1079. // [splitKey] -- The key last successfully written to
  1080. // disk (split key). If there is no key, set it to "MinKey".
  1081. //
  1082. // History: 4-10-94 srikants Created
  1083. //
  1084. // Notes:
  1085. //
  1086. //----------------------------------------------------------------------------
  1087. CPersComp::CPersComp(
  1088. CPhysIndex& phIndex,
  1089. WORKID widMax,
  1090. const BitOffset & bitOffRestart,
  1091. const BitOffset & bitOffSplitKey,
  1092. const CKeyBuf & splitKey)
  1093. : CKeyComp( phIndex, widMax, bitOffRestart, bitOffSplitKey, splitKey),
  1094. _sigPersComp(eSigPersComp),
  1095. _cWidProposed(0),
  1096. _cWidActual(0),
  1097. _bitStreamPatch ( phIndex )
  1098. {
  1099. #if CIDBG == 1
  1100. _cOccLeft = 0;
  1101. #endif // CIDBG == 1
  1102. }
  1103. //+---------------------------------------------------------------------------
  1104. //
  1105. // Member: CPersComp::~CPersComp, public
  1106. //
  1107. // Synopsis: Destroy a compressor/buffer pair.
  1108. //
  1109. // Effects: The main effect of destroying a compressor is that the
  1110. // associated buffer is also destroyed (presumably storing
  1111. // the data to a persistent medium).
  1112. //
  1113. // Signals: ???
  1114. //
  1115. // History: 05-Jul-91 KyleP Created.
  1116. //
  1117. // Notes: Previous compressor is deleted in PutKey
  1118. //
  1119. //----------------------------------------------------------------------------
  1120. CPersComp::~CPersComp()
  1121. {
  1122. ciDebugOut (( DEB_PCOMP,"CPersComp::~CPersComp() -- Last Key = %.*ws\n",
  1123. _key.StrLen(), _key.GetStr() ));
  1124. }
  1125. //+---------------------------------------------------------------------------
  1126. //
  1127. // Member: CPersComp::PatchWidCount, private
  1128. //
  1129. // Synopsis: Overwrites wid count
  1130. //
  1131. // History: 06-Nov-91 BartoszM Created.
  1132. //
  1133. //----------------------------------------------------------------------------
  1134. inline void CPersComp::PatchWidCount ()
  1135. {
  1136. if (_cWidProposed <= 15)
  1137. {
  1138. _bitStreamPatch.OverwriteBits(_cWidActual, 4);
  1139. }
  1140. else if (_cWidProposed <= 255)
  1141. {
  1142. _bitStreamPatch.OverwriteBits(_cWidActual, 12); // 4 0's + 8 bit number
  1143. }
  1144. else
  1145. {
  1146. _bitStreamPatch.OverwriteBits(0, 12); // 12 0's
  1147. _bitStreamPatch.OverwriteBits(_cWidActual, ULONG_BITS); // ULONG_BITS bit number
  1148. }
  1149. }
  1150. //+---------------------------------------------------------------------------
  1151. //
  1152. // Member: CPersComp::PutWidCount, private
  1153. //
  1154. // Synopsis: Writes work id count
  1155. //
  1156. // Arguments: [cWorkId] -- Count of wid's
  1157. //
  1158. // History: 06-Nov-91 BartoszM Created.
  1159. //
  1160. // Notes: Store the workid count. First, store the WID count used for
  1161. // compression. We will store a 4 bit count. If the count is
  1162. // greater than 15 then a 4-bit 0 will be stored followed by an 8 bit
  1163. // count. If the count is greater than 255 then a 12-bit 0 will be
  1164. // stored followed by a ULONG_BITS bit count.
  1165. //
  1166. //----------------------------------------------------------------------------
  1167. inline void CPersComp::PutWidCount ( ULONG cWorkId )
  1168. {
  1169. Win4Assert(cWorkId > 0);
  1170. ciDebugOut (( DEB_PCOMP | DEB_NOCOMPNAME,
  1171. "[%d]", cWorkId ));
  1172. BitOffset off;
  1173. // Position the patch stream at current offset
  1174. _bitStream.GetOffset(off);
  1175. _bitStreamPatch.Seek(off);
  1176. if (cWorkId <= 15)
  1177. {
  1178. _bitStream.PutBits(cWorkId, 4);
  1179. }
  1180. else if (cWorkId <= 255)
  1181. {
  1182. _bitStream.PutBits(cWorkId, 12); // 4 0's + 8 bit number
  1183. }
  1184. else
  1185. {
  1186. _bitStream.PutBits(0, 12); // 12 0's
  1187. _bitStream.PutBits(cWorkId, ULONG_BITS); // ULONG_BITS bit number
  1188. }
  1189. //
  1190. // Store a single bit indicating whether the count is accurrate.
  1191. // Regardless of whether it is accurrate, it is used for encoding.
  1192. //
  1193. _bitStream.PutBits(1, 1);
  1194. }
  1195. //+---------------------------------------------------------------------------
  1196. //
  1197. // Member: CPersComp::SkipWidCount, private
  1198. //
  1199. // Synopsis: Skips wid count
  1200. //
  1201. // History: 06-Nov-91 BartoszM Created.
  1202. //
  1203. //----------------------------------------------------------------------------
  1204. inline void CPersComp::SkipWidCount ()
  1205. {
  1206. unsigned posDelta;
  1207. if (_cWidProposed <= 15)
  1208. posDelta = 4;
  1209. else if (_cWidProposed <= 255)
  1210. posDelta = 12;
  1211. else
  1212. posDelta = 12 + ULONG_BITS;
  1213. _bitStreamPatch.SkipBits(posDelta);
  1214. }
  1215. //+---------------------------------------------------------------------------
  1216. //
  1217. // Member: CPersComp::PutKey, public
  1218. //
  1219. // Synopsis: Starts recording data for a new key.
  1220. //
  1221. // Arguments: [key] -- The new key.
  1222. //
  1223. // [cWorkId] -- Count of work ids to follow.
  1224. //
  1225. // [bitOff] -- (out) actual bit offset of the key in the index
  1226. //
  1227. // History: 05-Jul-91 KyleP Created.
  1228. //
  1229. // Notes: The structure for each key is:
  1230. // Prefix/Suffix size
  1231. // Suffix
  1232. // Property ID
  1233. // Work ID count
  1234. //
  1235. //----------------------------------------------------------------------------
  1236. void CPersComp::PutKey(const CKeyBuf * pkey,
  1237. ULONG cWorkId,
  1238. BitOffset & bitOffCurKey)
  1239. {
  1240. Win4Assert(_cOccLeft == 0);
  1241. Win4Assert(cWorkId > 0);
  1242. #if 0
  1243. if ( ( _cWidActual == 0 ) && ( _cWidProposed != 0 ) )
  1244. {
  1245. BackSpace();
  1246. }
  1247. else
  1248. {
  1249. #endif // 0
  1250. //
  1251. // Set the WorkId count accuracy bit for the previous key (if any).
  1252. // Then reset the workid counter.
  1253. //
  1254. SetCWIDAccuracy();
  1255. #if 0
  1256. }
  1257. #endif // 0
  1258. CKeyComp::PutKey(pkey, bitOffCurKey);
  1259. //
  1260. // Assume that a cursor just counted a few too many workids.
  1261. // If the final workid count is > _widMaximum that is very bad.
  1262. //
  1263. if ( cWorkId > _widMaximum )
  1264. cWorkId = _widMaximum;
  1265. PutWidCount ( cWorkId );
  1266. //
  1267. // Set up per/workid state
  1268. //
  1269. SetAverageBits ( cWorkId );
  1270. _wid = 0;
  1271. _cWidProposed = cWorkId;
  1272. _cWidActual = 0;
  1273. #if CIDBG == 1
  1274. _cOccLeft = 0;
  1275. #endif
  1276. }
  1277. //+---------------------------------------------------------------------------
  1278. //
  1279. // Member: CPersComp::PutWorkId, public
  1280. //
  1281. // Synopsis: Store a new WorkId.
  1282. //
  1283. // Arguments: [wid] -- WorkId
  1284. // [maxOcc] -- Max occurrence of wid
  1285. // [cOccurrence] -- Count of occurrences to follow
  1286. //
  1287. // Requires: [wid] must be larger than the last WorkId stored in
  1288. // the current key.
  1289. //
  1290. // Modifies: The input is added to the new index.
  1291. //
  1292. // History: 08-Jul-91 KyleP Created.
  1293. //
  1294. //----------------------------------------------------------------------------
  1295. void CPersComp::PutWorkId(WORKID wid, OCCURRENCE maxOcc, ULONG cOccurrence)
  1296. {
  1297. Win4Assert(wid != widInvalid);
  1298. Win4Assert(wid > 0);
  1299. Win4Assert( wid > _wid );
  1300. Win4Assert( _cbitAverageWid > 0 );
  1301. Win4Assert(wid <= _widMaximum);
  1302. Win4Assert(_cOccLeft == 0);
  1303. Win4Assert( cOccurrence > 0 );
  1304. ciDebugOut (( DEB_PCOMP | DEB_NOCOMPNAME,"<%d>", wid ));
  1305. //
  1306. // Store the workid delta.
  1307. //
  1308. BitCompress(wid - _wid, _cbitAverageWid);
  1309. //
  1310. // Store the max occurrence
  1311. //
  1312. PutMaxOccurrence( maxOcc );
  1313. //
  1314. // And store the occurrence count.
  1315. //
  1316. ciDebugOut (( DEB_PCOMP | DEB_NOCOMPNAME,"(%d)", cOccurrence ));
  1317. BitCompress(cOccurrence, OccCountBits);
  1318. //
  1319. // Update state
  1320. //
  1321. _wid = wid;
  1322. _occ = 0;
  1323. _cWidActual++;
  1324. #if CIDBG == 1
  1325. _cOccLeft = cOccurrence;
  1326. #endif
  1327. }
  1328. //+---------------------------------------------------------------------------
  1329. //
  1330. // Member: CPersComp::PutMaxOccurrence
  1331. //
  1332. // Synopsis: Writes the max occurrence using the same compression
  1333. // scheme as that for writing widCount
  1334. //
  1335. // Arguments: [maxOcc] -- Max occurrence to write
  1336. //
  1337. // History: 20-Jun-96 SitaramR Created
  1338. //
  1339. //----------------------------------------------------------------------------
  1340. void CPersComp::PutMaxOccurrence( OCCURRENCE maxOcc )
  1341. {
  1342. Win4Assert( maxOcc > 0 );
  1343. ciDebugOut (( DEB_PCOMP | DEB_NOCOMPNAME, "[%d]", maxOcc ));
  1344. if ( maxOcc <= 15 )
  1345. {
  1346. _bitStream.PutBits( maxOcc, 4 );
  1347. }
  1348. else if ( maxOcc <= 255 )
  1349. {
  1350. _bitStream.PutBits( maxOcc, 12 ); // 4 0's + 8 bit number
  1351. }
  1352. else
  1353. {
  1354. _bitStream.PutBits( 0, 12 ); // 12 0's
  1355. _bitStream.PutBits( maxOcc, ULONG_BITS ); // ULONG_BITS bit number
  1356. }
  1357. }
  1358. //+---------------------------------------------------------------------------
  1359. //
  1360. // Member: CPersComp::SetCWIDAccuracy, private
  1361. //
  1362. // Effects: Determines if the originally specified number of WorkIds
  1363. // was accurate, and sets the 'accuracy' bit in the key
  1364. // accordingly.
  1365. //
  1366. // Modifies: The most recent 'accuracy' bit may be changed. This may
  1367. // be in a previous compressor or the current compressor.
  1368. //
  1369. // History: 18-Jul-91 KyleP Created.
  1370. //
  1371. // Notes: The only time additional space is needed is when we have
  1372. // an inaccurate count which cannot be fixed up.
  1373. //
  1374. //----------------------------------------------------------------------------
  1375. void CPersComp::SetCWIDAccuracy()
  1376. {
  1377. Win4Assert(_cWidActual <= _widMaximum);
  1378. //
  1379. // If the count was accurrate, then do nothing except delete the
  1380. // previous compressor (if any). If the count is inaccurate, then
  1381. // set the 'accuracy' bit.
  1382. //
  1383. if (_cWidActual != _cWidProposed)
  1384. {
  1385. //
  1386. // Decide if the count can be fixed up without having to shift
  1387. // any previously written data. This can generally be accomplished
  1388. // if the real count is either smaller than the proposed count or
  1389. // not too much larger *and* _cbitAverageWid remains the same.
  1390. //
  1391. Win4Assert ( _cWidActual <= _widMaximum );
  1392. if ( _cWidActual != 0 &&
  1393. _cbitAverageWid == AverageWidBits(_cWidActual) )
  1394. {
  1395. // ciDebugOut (( DEB_PCOMP, "fixed.\n"));
  1396. Win4Assert(_cWidActual < _cWidProposed);
  1397. PatchWidCount ();
  1398. }
  1399. else
  1400. {
  1401. //
  1402. // If we can't fix the count, then just set the 'count invalid' bit.
  1403. // And append a workid delta of 0.
  1404. //
  1405. // ciDebugOut (( DEB_PCOMP, "not fixed.\n"));
  1406. //
  1407. // Read forward over the count.
  1408. //
  1409. SkipWidCount ();
  1410. //
  1411. // And set the count invalid bit
  1412. //
  1413. #if CIDBG == 1
  1414. if (_bitStreamPatch.PeekBit() != 1)
  1415. {
  1416. Dump();
  1417. Win4Assert ( _bitStreamPatch.PeekBit() == 1 );
  1418. }
  1419. #endif // CIDBG == 1
  1420. _bitStreamPatch.OverwriteBits(0, 1);
  1421. //
  1422. // Store the sentinel workid delta.
  1423. //
  1424. ciDebugOut (( DEB_PCOMP | DEB_NOCOMPNAME," end "));
  1425. BitCompress(0, _cbitAverageWid);
  1426. }
  1427. _cWidActual = 0;
  1428. _cWidProposed = 0;
  1429. }
  1430. }
  1431. //+---------------------------------------------------------------------------
  1432. //
  1433. // Member: CPersDeComp::CPersDeComp, public
  1434. //
  1435. // Synopsis: Creates a new persistent decompressor
  1436. // at the beginning of an index
  1437. //
  1438. // Arguments: [iid] -- index id
  1439. // [phIndex] -- physical index
  1440. // [widMax] -- Maximum workid which may be in the buffer.
  1441. // This must be the same number was was used
  1442. // during compression.
  1443. // [fUseDir] -- Flag indicating if the directory should be
  1444. // used or not for decompressing. Normally set to FALSE but
  1445. // during an in-progress master merge, we may not have a
  1446. // directory constructed yet.
  1447. //
  1448. // History: 12-Jul-91 KyleP Created.
  1449. // 21-Apr-92 BartoszM Split into two constructors
  1450. // 10-Apr=94 SrikantS Added fUseDir for restarted master
  1451. // merge.
  1452. //
  1453. //----------------------------------------------------------------------------
  1454. CPersDeComp::CPersDeComp(
  1455. PDirectory& pDir,
  1456. INDEXID iid,
  1457. CPhysIndex& phIndex,
  1458. WORKID widMax,
  1459. BOOL fUseLinks,
  1460. BOOL fUseDir )
  1461. : CKeyDeComp( pDir, iid, phIndex, widMax, fUseLinks, fUseDir ),
  1462. _sigPersDeComp(eSigPersDeComp)
  1463. {
  1464. FinishKeyLoad();
  1465. }
  1466. //+---------------------------------------------------------------------------
  1467. //
  1468. // Member: CPersDeComp::CPersDeComp, public
  1469. //
  1470. // Synopsis: Creates a new persistent decompressor.
  1471. // positioned at a specified key
  1472. //
  1473. // Arguments: [iid] -- index id
  1474. // [phIndex] -- physical index
  1475. // [keyPos] -- bit offset to key stored in directory
  1476. // [keyInit] -- initial key
  1477. // [pKey] -- actual key to search for
  1478. // [widMax] -- Maximum workid which may be in the buffer.
  1479. // This must be the same number was was used
  1480. // during compression.
  1481. // [fUseDir] -- Flag indicating if the directory should be
  1482. // used or not for decompressing. Normally set to FALSE but
  1483. // during an in-progress master merge, we may not have a
  1484. // directory constructed yet.
  1485. //
  1486. // History: 12-Jul-91 KyleP Created.
  1487. // 21-Apr-92 BartoszM Split into two constructors
  1488. // 10-Apr=94 SrikantS Added fUseDir for restarted master
  1489. // merge.
  1490. //
  1491. //----------------------------------------------------------------------------
  1492. CPersDeComp::CPersDeComp(
  1493. PDirectory& pDir,
  1494. INDEXID iid,
  1495. CPhysIndex& phIndex,
  1496. BitOffset& keyPos,
  1497. const CKeyBuf& keyInit,
  1498. const CKey* pKey,
  1499. WORKID widMax,
  1500. BOOL fUseLinks,
  1501. BOOL fUseDir )
  1502. : CKeyDeComp( pDir, iid, phIndex, keyPos, keyInit, pKey, widMax,
  1503. fUseLinks, fUseDir ),
  1504. _sigPersDeComp(eSigPersDeComp),
  1505. _maxOcc(OCC_INVALID)
  1506. {
  1507. FinishKeyLoad();
  1508. CKeyCursor::_pid = _key.Pid();
  1509. UpdateWeight();
  1510. }
  1511. //+---------------------------------------------------------------------------
  1512. //
  1513. // Member: CPersDeComp::CPersDeComp, public
  1514. //
  1515. // Synopsis: Copy Constructor
  1516. //
  1517. // Effects: Copies most of the values in decomp. Calls copy constructor
  1518. // for CCoder.
  1519. //
  1520. // Arguments: [decomp] -- Original CPersDeComp to be copied.
  1521. //
  1522. // History: 08-Jan-92 AmyA Created.
  1523. //
  1524. //----------------------------------------------------------------------------
  1525. CPersDeComp::CPersDeComp(CPersDeComp & decomp)
  1526. :
  1527. CKeyDeComp (decomp),
  1528. _sigPersDeComp(eSigPersDeComp),
  1529. _cWid(decomp._cWid),
  1530. _cOcc(decomp._cOcc),
  1531. _fcwidAccurate(decomp._fcwidAccurate),
  1532. _cWidLeft(decomp._cWidLeft),
  1533. _cOccLeft(decomp._cOccLeft),
  1534. _maxOcc(OCC_INVALID)
  1535. {
  1536. UpdateWeight();
  1537. }
  1538. //+---------------------------------------------------------------------------
  1539. //
  1540. // Member: CPersDeComp::~CPersDeComp, public
  1541. //
  1542. // Synopsis: Destroy a decompressor/buffer pair.
  1543. //
  1544. // Effects: The main effect of destroying a decompressor is that the
  1545. // associated buffer is also destroyed (presumably storing
  1546. // the data to a persistent medium).
  1547. //
  1548. // Signals: ???
  1549. //
  1550. // History: 22-Jul-91 KyleP Created.
  1551. //
  1552. //----------------------------------------------------------------------------
  1553. CPersDeComp::~CPersDeComp()
  1554. {}
  1555. const CKeyBuf * CPersDeComp::GetNextKey()
  1556. {
  1557. return GetNextKey(0);
  1558. }
  1559. //+---------------------------------------------------------------------------
  1560. //
  1561. // Member: CPersDeComp::GetNextKey, public
  1562. //
  1563. // Synopsis: Retrieve the next key from the content index.
  1564. //
  1565. // Returns: A pointer to the key, or 0 if end of page/index reached.
  1566. //
  1567. // History: 15-Jul-91 KyleP Created.
  1568. // 10-Apr-94 SrikantS Added pBitOff and the ability to
  1569. // decompress without using the dir.
  1570. //
  1571. //----------------------------------------------------------------------------
  1572. const CKeyBuf * CPersDeComp::GetNextKey( BitOffset *pBitOff )
  1573. {
  1574. //
  1575. // If we are not using links or
  1576. // we are not using the directory and the offset of next key
  1577. // is invalid, we must skip over the wid/occurrence data and
  1578. // find out the offset of the next key.
  1579. //
  1580. if ( !_fUseLinks || (!_fUseDir && !_bitOffNextKey.Valid()) )
  1581. {
  1582. //
  1583. // Just iterate through any remaining data for this key.
  1584. //
  1585. while (_wid != widInvalid)
  1586. {
  1587. while ( 0 != _cOccLeft )
  1588. {
  1589. BitUnCompress( OccDeltaBits );
  1590. _cOccLeft--;
  1591. }
  1592. LoadWorkId();
  1593. }
  1594. if ( _fUseLinks )
  1595. {
  1596. //
  1597. // We should fill the bitoffset for the next key as
  1598. // the current position in the bitstream.
  1599. //
  1600. Win4Assert( !_fUseDir );
  1601. _bitStream.GetOffset( _bitOffNextKey );
  1602. }
  1603. }
  1604. const CKeyBuf * pkey = CKeyDeComp::GetNextKey( pBitOff );
  1605. if ( pkey )
  1606. {
  1607. FinishKeyLoad();
  1608. CKeyCursor::_pid = pkey->Pid();
  1609. UpdateWeight();
  1610. }
  1611. return pkey;
  1612. } //GetNextKey
  1613. //+---------------------------------------------------------------------------
  1614. //
  1615. // Member: CPersDeComp::WorkId, public
  1616. //
  1617. // Synopsis: Retrieves the current Work ID
  1618. //
  1619. // Returns: The current WorkId or, if there is none or if at the end
  1620. // of the compressor then returns widInvalid.
  1621. //
  1622. // History: 15-Jul-91 KyleP Created.
  1623. //
  1624. //----------------------------------------------------------------------------
  1625. WORKID CPersDeComp::WorkId()
  1626. {
  1627. return(_wid);
  1628. }
  1629. //+---------------------------------------------------------------------------
  1630. //
  1631. // Member: CPersDeComp::NextWorkId, public
  1632. //
  1633. // Synopsis: Retrieve the next workid from the content index.
  1634. //
  1635. // Returns: A pointer to the workid, or widInvalid if end of
  1636. // page/index reached.
  1637. //
  1638. // History: 15-Jul-91 KyleP Created.
  1639. //
  1640. //----------------------------------------------------------------------------
  1641. WORKID CPersDeComp::NextWorkId()
  1642. {
  1643. //
  1644. // Just iterate through any remaining data for this WorkId.
  1645. //
  1646. while ( 0 != _cOccLeft )
  1647. {
  1648. BitUnCompress( OccDeltaBits );
  1649. _cOccLeft--;
  1650. }
  1651. // _occ may be invalid and really should be OCC_INVALID, but it doesn't matter
  1652. LoadWorkId();
  1653. return _wid;
  1654. }
  1655. //+---------------------------------------------------------------------------
  1656. //
  1657. // Member: CPersDeComp::WorkIdCount, public
  1658. //
  1659. // Returns: The total count of workids for the current key.
  1660. //
  1661. // History: 15-Jul-91 KyleP Created.
  1662. //
  1663. // Notes: Unlike the Get* calls, it is illegal to get a workid count
  1664. // if there is no valid key.
  1665. //
  1666. //----------------------------------------------------------------------------
  1667. ULONG CPersDeComp::WorkIdCount()
  1668. {
  1669. Win4Assert( _key.Count() > 0 );
  1670. return(_cWid);
  1671. }
  1672. //+---------------------------------------------------------------------------
  1673. //
  1674. // Member: CPersDeComp::Occurrence, public
  1675. //
  1676. // Synopsis: Retrieves the current occurrence
  1677. //
  1678. // Returns: The current occurrence or, if there is none or if at the end
  1679. // of the compressor then returns OCC_INVALID.
  1680. //
  1681. // History: 15-Jul-91 KyleP Created.
  1682. //
  1683. //----------------------------------------------------------------------------
  1684. OCCURRENCE CPersDeComp::Occurrence()
  1685. {
  1686. return(_occ);
  1687. }
  1688. //+---------------------------------------------------------------------------
  1689. //
  1690. // Member: CPersDeComp::NextOccurrence, public
  1691. //
  1692. // Synopsis: Retrieve the next occurrence from the content index.
  1693. //
  1694. // Returns: A pointer to the occurrence, or OCC_INVALID if end of
  1695. // page/index reached.
  1696. //
  1697. // History: 15-Jul-91 KyleP Created.
  1698. //
  1699. //----------------------------------------------------------------------------
  1700. OCCURRENCE CPersDeComp::NextOccurrence()
  1701. {
  1702. LoadOccurrence();
  1703. return _occ;
  1704. }
  1705. //+---------------------------------------------------------------------------
  1706. //
  1707. // Member: CPersDeComp::OccurrenceCount, public
  1708. //
  1709. // Returns: The total count of occurrences for the current workid.
  1710. //
  1711. // History: 15-Jul-91 KyleP Created.
  1712. //
  1713. // Notes: Unlike the Get* calls, it is illegal to get an occ count
  1714. // if there is no valid workid.
  1715. //
  1716. //----------------------------------------------------------------------------
  1717. ULONG CPersDeComp::OccurrenceCount()
  1718. {
  1719. Win4Assert(_wid != widInvalid);
  1720. return(_cOcc);
  1721. }
  1722. //+---------------------------------------------------------------------------
  1723. //
  1724. // Member: CPersDeComp::LoadWidCount, private
  1725. //
  1726. // Synopsis: Loads wid count
  1727. //
  1728. // History: 05-Nov-91 BartoszM Created.
  1729. //
  1730. //----------------------------------------------------------------------------
  1731. inline void CPersDeComp::LoadWidCount ()
  1732. {
  1733. //
  1734. // Get the WorkId count. Initially assume it is 4 bits, then 8,
  1735. // then ULONG_BITS.
  1736. //
  1737. ULONG ul = _bitStream.GetBits(4);
  1738. ciDebugOut (( DEB_PCOMP | DEB_NOCOMPNAME, "{0x%x}", ul ));
  1739. if (ul == 0)
  1740. {
  1741. ul = _bitStream.GetBits(8);
  1742. if (ul == 0)
  1743. {
  1744. ul = _bitStream.GetBits(ULONG_BITS);
  1745. Win4Assert(ul != 0);
  1746. }
  1747. }
  1748. _cWid = _cWidLeft = ul;
  1749. //
  1750. // Get the bit signifying that the workid count is accurate.
  1751. //
  1752. ul = _bitStream.GetBits(1);
  1753. _fcwidAccurate = ul ? TRUE : FALSE;
  1754. ciDebugOut (( DEB_PCOMP | DEB_NOCOMPNAME,
  1755. "[%s%d]", _fcwidAccurate?"":"!", _cWid ));
  1756. }
  1757. //+---------------------------------------------------------------------------
  1758. //
  1759. // Member: CPersDeComp::LoadKey, private
  1760. //
  1761. // Synopsis: Loads data for the next key.
  1762. //
  1763. // Effects: Reads a key from the current position in _bitStream and
  1764. // sets per key state.
  1765. //
  1766. // Signals: ???
  1767. //
  1768. // History: 12-Jul-91 KyleP Created.
  1769. //
  1770. //----------------------------------------------------------------------------
  1771. void CPersDeComp::LoadKey()
  1772. {
  1773. CKeyDeComp::LoadKey();
  1774. FinishKeyLoad();
  1775. }
  1776. //+---------------------------------------------------------------------------
  1777. //
  1778. // Member: CPersDeComp::FinishKeyLoad, private
  1779. //
  1780. // Synopsis: Loads wid count and first wid. Finishes LoadKey call of
  1781. // CKeyDeComp
  1782. //
  1783. // History: 07-Dec-93 w-PatG Created.
  1784. //
  1785. //----------------------------------------------------------------------------
  1786. void CPersDeComp::FinishKeyLoad()
  1787. {
  1788. //Parent class has loaded in a key and id. Finish the job by loading in
  1789. //a wid count and first wid.
  1790. if ( IsAtSentinel() )
  1791. {
  1792. _wid = widInvalid;
  1793. _occ = OCC_INVALID;
  1794. _maxOcc = OCC_INVALID;
  1795. return;
  1796. }
  1797. LoadWidCount ();
  1798. _wid = 0;
  1799. #if CIDBG == 1
  1800. if ( _cWid > _widMaximum )
  1801. ciDebugOut (( DEB_ERROR, "_cWid = %ld, _widMaximum = %ld\n",
  1802. _cWid, _widMaximum ));
  1803. #endif
  1804. Win4Assert ( _cWid <= _widMaximum );
  1805. SetAverageBits( _cWid );
  1806. LoadWorkId();
  1807. }
  1808. //+---------------------------------------------------------------------------
  1809. //
  1810. // Member: CPersDeComp::LoadOccurrence, private
  1811. //
  1812. // Synopsis: Load an occurrence from the bit buffer.
  1813. //
  1814. // History: 15-Jul-91 KyleP Created.
  1815. //
  1816. //----------------------------------------------------------------------------
  1817. __forceinline void CPersDeComp::LoadOccurrence()
  1818. {
  1819. if (_cOccLeft == 0)
  1820. {
  1821. _occ = OCC_INVALID;
  1822. return;
  1823. }
  1824. ULONG occDelta = BitUnCompress(OccDeltaBits);
  1825. Win4Assert( occDelta > 0 );
  1826. _occ += occDelta;
  1827. _cOccLeft--;
  1828. ciDebugOut (( DEB_PCOMP | DEB_NOCOMPNAME, "%d ", _occ ));
  1829. }
  1830. //+---------------------------------------------------------------------------
  1831. //
  1832. // Member: CPersDeComp::LoadFirstOccurrence, private
  1833. //
  1834. // Synopsis: Load an occurrence from the bit buffer.
  1835. //
  1836. // History: 15-Jul-91 KyleP Created.
  1837. //
  1838. //----------------------------------------------------------------------------
  1839. __forceinline void CPersDeComp::LoadFirstOccurrence()
  1840. {
  1841. Win4Assert( 0 != _cOccLeft );
  1842. _occ = BitUnCompress(OccDeltaBits);
  1843. Win4Assert( _occ > 0 );
  1844. _cOccLeft--;
  1845. ciDebugOut (( DEB_PCOMP | DEB_NOCOMPNAME, "%d ", _occ ));
  1846. }
  1847. //+---------------------------------------------------------------------------
  1848. //
  1849. // Member: CPersDeComp::LoadMaxOccurrence
  1850. //
  1851. // Synopsis: Load max occurrence from the bit buffer.
  1852. //
  1853. // History: 20-Jun-96 SitaramR Created
  1854. //
  1855. //----------------------------------------------------------------------------
  1856. __forceinline void CPersDeComp::LoadMaxOccurrence()
  1857. {
  1858. //
  1859. // Initially assume it is 4 bits, then 8, then ULONG_BITS
  1860. //
  1861. _maxOcc = _bitStream.GetBits(4);
  1862. if ( _maxOcc == 0 )
  1863. {
  1864. _maxOcc = _bitStream.GetBits(8);
  1865. if ( _maxOcc == 0 )
  1866. {
  1867. _maxOcc = _bitStream.GetBits(ULONG_BITS);
  1868. Win4Assert( _maxOcc != 0 );
  1869. }
  1870. }
  1871. ciDebugOut (( DEB_PCOMP | DEB_NOCOMPNAME, "{0x%x}", _maxOcc ));
  1872. }
  1873. //+---------------------------------------------------------------------------
  1874. //
  1875. // Member: CPersDeComp::LoadWorkId, private
  1876. //
  1877. // Synopsis: Loads data for a WorkId.
  1878. //
  1879. // History: 15-Jul-91 KyleP Created.
  1880. //
  1881. //----------------------------------------------------------------------------
  1882. void CPersDeComp::LoadWorkId()
  1883. {
  1884. if (_cWidLeft == 0)
  1885. {
  1886. Win4Assert(_fcwidAccurate);
  1887. _wid = widInvalid;
  1888. return;
  1889. }
  1890. ULONG widDelta = BitUnCompress( _cbitAverageWid);
  1891. if (widDelta == 0)
  1892. {
  1893. #if CIDBG == 1
  1894. if (_fcwidAccurate)
  1895. Dump();
  1896. #endif
  1897. Win4Assert(!_fcwidAccurate);
  1898. _wid = widInvalid;
  1899. return;
  1900. }
  1901. LoadMaxOccurrence();
  1902. ULONG occCount = BitUnCompress( OccCountBits);
  1903. _wid += widDelta;
  1904. ciDebugOut (( DEB_PCOMP | DEB_NOCOMPNAME, "<%d>", _wid ));
  1905. Win4Assert(_wid <= _widMaximum);
  1906. _cOcc = _cOccLeft = occCount;
  1907. _cWidLeft--;
  1908. ciDebugOut (( DEB_PCOMP | DEB_NOCOMPNAME, "(%d)", _cOcc ));
  1909. LoadFirstOccurrence();
  1910. }
  1911. #if DEVL == 1
  1912. void CCoder::Dump()
  1913. {
  1914. #if CIDBG == 1
  1915. ciDebugOut((DEB_ITRACE,
  1916. "CCoder:\n"
  1917. "\t_widMaximum %d\n"
  1918. "\tKey \"%.*ws\"\n"
  1919. "\t_wid %d"
  1920. "\t_occ %d\n"
  1921. "\t_cbitAverageWid %d\n",
  1922. _widMaximum, _key.StrLen(), _key.GetStr(), _wid, _occ, _cbitAverageWid ));
  1923. #endif // CIDBG == 1
  1924. }
  1925. void CKeyComp::Dump()
  1926. {
  1927. }
  1928. void CKeyDeComp::Dump()
  1929. {
  1930. }
  1931. void CPersDeComp::Dump()
  1932. {
  1933. #if CIDBG == 1
  1934. CCoder::Dump();
  1935. ciDebugOut((DEB_ITRACE,
  1936. "CPersDeComp:\n"
  1937. "\t_cWid %d\n"
  1938. "\t_cOcc %d\n"
  1939. "\t_fcwidAccurate %d"
  1940. "\t_cWidLeft %d\n"
  1941. "\t_cOccLeft %d\n",
  1942. _cWid, _cOcc, _fcwidAccurate, _cWidLeft, _cOccLeft ));
  1943. _bitStream.Dump();
  1944. #endif // CIDBG == 1
  1945. }
  1946. void CPersComp::Dump()
  1947. {
  1948. #if CIDBG == 1
  1949. CCoder::Dump();
  1950. ciDebugOut((DEB_ITRACE,
  1951. "CPersComp:\n"
  1952. "\t_cWidActual %d\n"
  1953. "\t_cWidProposed %d\n"
  1954. "\t_cOccLeft %d\n",
  1955. _cWidActual, _cWidProposed, _cOccLeft ));
  1956. ciDebugOut((DEB_ITRACE, "BitStream\n" ));
  1957. _bitStream.Dump();
  1958. ciDebugOut((DEB_ITRACE, "BitStreamPatch\n" ));
  1959. _bitStreamPatch.Dump();
  1960. #endif // CIDBG == 1
  1961. }
  1962. #endif // DEVL == 1