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.

782 lines
23 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1994 - 2000.
  5. //
  6. // File: strhash.cxx
  7. //
  8. // Contents: Hash table compressions of strings for large tables.
  9. //
  10. // Classes: CCompressedColHashString
  11. //
  12. // Functions:
  13. //
  14. // History: 03 May 1994 AlanW Created
  15. //
  16. //--------------------------------------------------------------------------
  17. #include "pch.cxx"
  18. #pragma hdrstop
  19. #include <tblvarnt.hxx>
  20. #include "strhash.hxx"
  21. //+---------------------------------------------------------------------------
  22. //
  23. // Function: HashWSTR
  24. //
  25. // Synopsis: Hashes a WSTR and returns a value according to the format
  26. // explained in the HashString call.
  27. //
  28. // Arguments: [pwszStr] - Pointer to the string.
  29. // [nChar] - Number of characters in the string.
  30. //
  31. // Returns: A HashValue (formatted according to notes in HashString)
  32. //
  33. // History: 5-19-95 srikants Created
  34. //
  35. // Notes:
  36. //
  37. //----------------------------------------------------------------------------
  38. inline
  39. ULONG CCompressedColHashString::HashWSTR( WCHAR const * pwszStr,
  40. USHORT nChar )
  41. {
  42. ULONG ulRet = 0;
  43. for ( ULONG i = 0; i < nChar ; i++)
  44. {
  45. WCHAR wch = pwszStr[i];
  46. ulRet = (ulRet << 1) ^ wch;
  47. }
  48. ulRet = (ulRet >> 16) ^ ulRet;
  49. ulRet = (ulRet & 0xFFFF) | (i << 17);
  50. return ulRet;
  51. }
  52. //+---------------------------------------------------------------------------
  53. //
  54. // Function: HashSTR
  55. //
  56. // Synopsis: Hashes an ASCII string.
  57. //
  58. // Arguments: [pszStr] -
  59. // [nChar] -
  60. //
  61. // Returns: (Same as HashWSTR)
  62. //
  63. // History: 5-19-95 srikants Created
  64. //
  65. // Notes:
  66. //
  67. //----------------------------------------------------------------------------
  68. inline
  69. ULONG CCompressedColHashString::HashSTR( CHAR const * pszStr, USHORT nChar )
  70. {
  71. ULONG ulRet = 0;
  72. for ( ULONG i = 0; i < nChar ; i++)
  73. {
  74. BYTE ch = (BYTE) pszStr[i];
  75. ulRet = (ulRet << 1) ^ ch;
  76. }
  77. ulRet = (ulRet >> 16) ^ ulRet;
  78. ulRet = (ulRet & 0xFFFF) | (i << 17) | (1 << 16); // is an ascii string
  79. return ulRet;
  80. }
  81. //const ULONG CCompressedColHashString::_cbDataWidth = sizeof (HashEntry);
  82. //+-------------------------------------------------------------------------
  83. //
  84. // Method: CCompressedColHashString::HashString, public static
  85. //
  86. // Synopsis: Generic hash function for strings
  87. //
  88. // Arguments: [pbData] - pointer to the value to be hashed.
  89. // [cbData] - size of pbData (may be some arbitrary large
  90. // value if string is NUL terminated.
  91. // [vtDataType] - type of string, VT_LPWSTR, or VT__LPSTR
  92. // [fNullTerminated ] - Set to TRUE if the string is a NULL
  93. // terminted string. FALSE o/w.
  94. //
  95. // Returns: ULONG - Hash value for the input data
  96. //
  97. // Notes: The returned hash value encodes the string length in
  98. // characters and string format in the upper half of the
  99. // returned DWORD. The format of the returned value is:
  100. //
  101. // +15 00+
  102. // +-----------------------------------------------+
  103. // | hash value (xor,shift of char values) |
  104. // +--------------------------------------------+--+
  105. // | character count | F|
  106. // +--------------------------------------------+--+
  107. // 31 17+16+
  108. //
  109. // where F = 0 if Unicode string, F = 1 if ASCII string
  110. //
  111. // As a side-effect, the string is copied to local storage,
  112. // and a key to that storage is returned in rulCopyKey.
  113. //
  114. //--------------------------------------------------------------------------
  115. ULONG CCompressedColHashString::HashString(
  116. BYTE *pbData,
  117. USHORT cbData,
  118. VARTYPE vtDataType,
  119. BOOL fNullTerminated
  120. )
  121. {
  122. ULONG ulRet = 0;
  123. switch (vtDataType)
  124. {
  125. case VT_LPWSTR:
  126. {
  127. UNICODE_STRING ustr;
  128. if ( fNullTerminated )
  129. {
  130. RtlInitUnicodeString(&ustr, (PWSTR)pbData);
  131. }
  132. else
  133. {
  134. Win4Assert( ( cbData & (USHORT) 0x1 ) == 0 ); // must be an even number
  135. ustr.Buffer = (PWSTR) pbData;
  136. ustr.MaximumLength = ustr.Length = cbData;
  137. }
  138. ulRet = HashWSTR( ustr.Buffer, ustr.Length/sizeof(WCHAR) );
  139. }
  140. break;
  141. case VT_LPSTR:
  142. {
  143. ANSI_STRING astr;
  144. if ( fNullTerminated )
  145. {
  146. RtlInitAnsiString(&astr, (PSZ)pbData);
  147. }
  148. else
  149. {
  150. astr.Buffer = (CHAR *) pbData;
  151. astr.MaximumLength = astr.Length = cbData;
  152. }
  153. ulRet = HashSTR( astr.Buffer, astr.Length );
  154. }
  155. break;
  156. default: // PERFFIX - need to support VT_BSTR also?
  157. Win4Assert(!"CCompressedColHashString::HashString called with bad type");
  158. THROW( CException( STATUS_INVALID_PARAMETER ) );
  159. }
  160. return ulRet;
  161. }
  162. //+-------------------------------------------------------------------------
  163. //
  164. // Method: CCompressedColHashString::AddData, public
  165. //
  166. // Synopsis: Add a data entry to the hash table if it is not
  167. // already there.
  168. //
  169. // Arguments: [pVarnt] - pointer to data item
  170. // [pKey] - pointer to lookup key value
  171. // [reIndicator] - returns an indicator variable for
  172. // problems
  173. //
  174. // Returns: pKey is filled in with the index of the data item in
  175. // the data array. reIndicator is filled with an indication
  176. // of problems.
  177. //
  178. // Notes:
  179. //
  180. //--------------------------------------------------------------------------
  181. VOID CCompressedColHashString::AddData(
  182. PROPVARIANT const * const pVarnt,
  183. ULONG* pKey,
  184. GetValueResult& reIndicator
  185. )
  186. {
  187. //
  188. // Specially handle the VT_EMPTY case
  189. //
  190. if (pVarnt->vt == VT_EMPTY) {
  191. *pKey = 0;
  192. reIndicator = GVRSuccess;
  193. return;
  194. }
  195. CTableVariant *pVar = (CTableVariant *)pVarnt;
  196. Win4Assert((pVar->vt == VT_LPWSTR || pVar->vt == VT_LPSTR) &&
  197. pVar->VariantPointerInFirstWord( ));
  198. BYTE *pbData ;
  199. USHORT cbData = (USHORT) pVar->VarDataSize();
  200. pbData = (BYTE *) pVar->pwszVal;
  201. Win4Assert(cbData != 0 && pbData != NULL);
  202. _AddData( pbData, cbData, pVar->vt, pKey, TRUE ); // NULL Terminated
  203. reIndicator = GVRSuccess;
  204. return;
  205. }
  206. //+---------------------------------------------------------------------------
  207. //
  208. // Function: FindCountedWStr
  209. //
  210. // Synopsis: Findss the given string to the string store. It is assumed
  211. // that there is no terminating NULL in the string. Instead,
  212. // its length is passed.
  213. //
  214. // Arguments: [pwszStr] - Pointer to the string to be added.
  215. // [cwcStr] - Count of the characters in the string.
  216. //
  217. // Returns: ULONG key or stridInvalid
  218. //
  219. // History: 7-17-95 dlee Created
  220. //
  221. //----------------------------------------------------------------------------
  222. ULONG CCompressedColHashString::FindCountedWStr(
  223. WCHAR const *pwszStr,
  224. ULONG cwcStr )
  225. {
  226. Win4Assert( !_fOptimizeAscii );
  227. BYTE *pbData = (BYTE *) pwszStr ;
  228. USHORT cbData = (USHORT) cwcStr * sizeof(WCHAR);
  229. Win4Assert(cbData != 0 && pbData != NULL);
  230. return _FindData( pbData, cbData, VT_LPWSTR, FALSE );
  231. } //FindCountedWStr
  232. //+---------------------------------------------------------------------------
  233. //
  234. // Function: AddCountedWStr
  235. //
  236. // Synopsis: Adds the given string to the string store. It is assumed
  237. // that there is no terminating NULL in the string. Instead,
  238. // its length is passed.
  239. //
  240. // Arguments: [pwszStr] - Pointer to the string to be added.
  241. // [cwcStr] - Count of the characters in the string.
  242. // [key] - OUTPUT - Id of the string
  243. // [reIndicator] - GVRSuccess if successful. Failure code o/w
  244. //
  245. // History: 5-19-95 srikants Created
  246. //
  247. // Notes:
  248. //
  249. //----------------------------------------------------------------------------
  250. VOID CCompressedColHashString::AddCountedWStr(
  251. WCHAR const *pwszStr,
  252. ULONG cwcStr,
  253. ULONG & key,
  254. GetValueResult & reIndicator
  255. )
  256. {
  257. Win4Assert( !_fOptimizeAscii );
  258. BYTE *pbData = (BYTE *) pwszStr ;
  259. USHORT cbData = (USHORT) cwcStr * sizeof(WCHAR);
  260. Win4Assert(cbData != 0 && pbData != NULL);
  261. _AddData( pbData, cbData, VT_LPWSTR, &key, FALSE );
  262. reIndicator = GVRSuccess;
  263. return;
  264. }
  265. //+---------------------------------------------------------------------------
  266. //
  267. // Function: AddData
  268. //
  269. // Synopsis: Adds a NULL terminated string to the string store.
  270. //
  271. // Arguments: [pwszStr] - Pointer to a NULL terminated string.
  272. // [key] - OUTPUT - key of the added string.
  273. // [reIndicator] - Status indicator.
  274. //
  275. // History: 5-19-95 srikants Created
  276. //
  277. // Notes:
  278. //
  279. //----------------------------------------------------------------------------
  280. VOID CCompressedColHashString::AddData(
  281. WCHAR const *pwszStr,
  282. ULONG & key,
  283. GetValueResult & reIndicator
  284. )
  285. {
  286. ULONG cwcStr = wcslen( pwszStr );
  287. AddCountedWStr( pwszStr, cwcStr, key, reIndicator );
  288. return;
  289. }
  290. //+-------------------------------------------------------------------------
  291. //
  292. // Method: CCompressedColHashString::_AddData, private
  293. //
  294. // Synopsis: Private helper for the public AddData method. Adds
  295. // a data entry to the hash table (if it does not already
  296. // exist).
  297. //
  298. // Arguments: [pbData] - pointer to data item
  299. // [cbDataSize] - size of data item
  300. // [pKey] - pointer to lookup key value
  301. //
  302. // Returns: pKey is filled in with the index of the data item in
  303. // the data array.
  304. //
  305. // Notes:
  306. //
  307. //--------------------------------------------------------------------------
  308. VOID CCompressedColHashString::_AddData(
  309. BYTE *pbData,
  310. USHORT cbDataSize,
  311. VARTYPE vt,
  312. ULONG* pKey,
  313. BOOL fNullTerminated
  314. ) {
  315. if ( 0 == _cDataItems )
  316. {
  317. _GrowHashTable();
  318. }
  319. ULONG ulHash = HashString( pbData, cbDataSize, vt, fNullTerminated );
  320. USHORT usSizeFmt = (USHORT) (ulHash >> 16);
  321. ULONG cbString = usSizeFmt & 1? usSizeFmt >> 1 : usSizeFmt;
  322. ulHash %= _cHashEntries;
  323. HASHKEY* pulHashChain = &(((HASHKEY *)_pAlloc->BufferAddr())[ulHash]);
  324. HashEntry* pNextData;
  325. USHORT cChainLength = 0;
  326. while (*pulHashChain != 0)
  327. {
  328. cChainLength++;
  329. pNextData = _IndexHashkey( *pulHashChain );
  330. if (usSizeFmt == pNextData->usSizeFmt)
  331. {
  332. BYTE* pbNextString = (BYTE*)_pAlloc->OffsetToPointer(pNextData->ulStringKey);
  333. if (memcmp(pbNextString, pbData, cbString) == 0)
  334. {
  335. //
  336. // Found the data item. Return its index.
  337. //
  338. *pKey = *pulHashChain;
  339. return;
  340. }
  341. }
  342. pulHashChain = &pNextData->ulHashChain;
  343. }
  344. //
  345. // Allocate memory for the new string and copy the contents from
  346. // the source buffer.
  347. //
  348. BYTE * pbNewData = (BYTE *) _pAlloc->Allocate( cbString );
  349. TBL_OFF ulKey = _pAlloc->PointerToOffset(pbNewData);
  350. RtlCopyMemory( pbNewData, pbData, cbString );
  351. // The table may move in memory when we call AllocFixed.
  352. // Be sure we can address pulHashChain after that.
  353. //
  354. ULONG ulHashChainBase = (ULONG)((BYTE*)pulHashChain - _pAlloc->BufferAddr());
  355. pNextData = (struct HashEntry*) _pAlloc->AllocFixed();
  356. pulHashChain = (HASHKEY *) (_pAlloc->BufferAddr() + ulHashChainBase);
  357. //
  358. // NOTE: The fixed hash table at this point decides if it wants
  359. // to grow the fixed area, with a possible rehash of the
  360. // table to grow the number of buckets. With the code
  361. // below, the string hash table has no opportunity to
  362. // grow the number of hash buckets.
  363. //
  364. //
  365. // Now add the new data item. The data item consists of a HASHKEY
  366. // for the hash chain, followed by the size and format indicator,
  367. // and the key for the string in the variable data.
  368. //
  369. *pKey = *pulHashChain = ++_cDataItems;
  370. Win4Assert(_cDataItems != 0); // check for overflow
  371. pNextData->ulHashChain = 0;
  372. pNextData->usSizeFmt = usSizeFmt;
  373. pNextData->ulStringKey = ulKey;
  374. }
  375. //+-------------------------------------------------------------------------
  376. //
  377. // Method: CCompressedColHashString::_FindData, private
  378. //
  379. // Synopsis: Finds a data entry in the hash table.
  380. //
  381. // Arguments: [pbData] - pointer to data item
  382. // [cbDataSize] - size of data item
  383. // [pKey] - pointer to lookup key value
  384. //
  385. // Returns: The key of the string or stridInvalid
  386. //
  387. // History: 7-17-95 dlee Created
  388. //
  389. //--------------------------------------------------------------------------
  390. ULONG CCompressedColHashString::_FindData(
  391. BYTE * pbData,
  392. USHORT cbDataSize,
  393. VARTYPE vt,
  394. BOOL fNullTerminated )
  395. {
  396. if ( 0 == _pAlloc )
  397. _GrowHashTable();
  398. ULONG ulHash = HashString( pbData, cbDataSize, vt, fNullTerminated );
  399. USHORT usSizeFmt = (USHORT) (ulHash >> 16);
  400. ULONG cbString = usSizeFmt & 1? usSizeFmt >> 1 : usSizeFmt;
  401. ulHash %= _cHashEntries;
  402. HASHKEY* pulHashChain = &(((HASHKEY *)_pAlloc->BufferAddr())[ulHash]);
  403. while ( 0 != *pulHashChain )
  404. {
  405. HashEntry* pNextData = _IndexHashkey( *pulHashChain );
  406. if ( usSizeFmt == pNextData->usSizeFmt )
  407. {
  408. BYTE* pbNext = (BYTE*)_pAlloc->OffsetToPointer(pNextData->ulStringKey);
  409. if ( memcmp( pbNext, pbData, cbString ) == 0 )
  410. {
  411. // Found the data item. Return its index.
  412. return *pulHashChain;
  413. }
  414. }
  415. pulHashChain = &pNextData->ulHashChain;
  416. }
  417. // couldn't find the string in the table
  418. return stridInvalid;
  419. } //_FindData
  420. //+-------------------------------------------------------------------------
  421. //
  422. // Method: CCompressedColHashString::GetData, public
  423. //
  424. // Synopsis: Retrieve a data value from the hash table.
  425. //
  426. // Arguments: [pVarnt] - pointer to a variant structure in which to
  427. // return a pointer to the data
  428. // [PreferredType] - preferred type of the result.
  429. // [ulKey] - the lookup key value
  430. // [PropId] - (unused) property id being retrieved.
  431. //
  432. // Returns: pVarnt is filled in with the data item from the hash table.
  433. //
  434. // Notes: The FreeVariant method must be called with the pVarnt
  435. // structure as an argument when it is no longer needed.
  436. //
  437. //--------------------------------------------------------------------------
  438. GetValueResult CCompressedColHashString::GetData(
  439. PROPVARIANT * pVarnt,
  440. VARTYPE PreferredType,
  441. ULONG ulKey,
  442. PROPID PropId
  443. )
  444. {
  445. Win4Assert(ulKey <= _cDataItems);
  446. if (ulKey == 0) {
  447. pVarnt->vt = VT_EMPTY;
  448. return GVRNotAvailable;
  449. }
  450. HashEntry* pData = ((HashEntry*) _pAlloc->FirstRow()) + ulKey - 1;
  451. BOOL fAscii = (pData->usSizeFmt & 1) != 0;
  452. ULONG cchSize = (pData->usSizeFmt >> 1) + 1;
  453. ULONG cbSize = PreferredType == VT_LPWSTR ? cchSize * sizeof (WCHAR) :
  454. !fAscii ? cchSize * sizeof (WCHAR) :
  455. cchSize;
  456. BYTE* pbBuf = (BYTE*)_GetStringBuffer((cbSize+1) / sizeof (WCHAR));
  457. BYTE* pbSource = (BYTE*)_pAlloc->OffsetToPointer(pData->ulStringKey);
  458. //
  459. // Give out the data as an LPSTR only if that's what the caller
  460. // desires, and it's in the ascii range.
  461. //
  462. if (PreferredType == VT_LPSTR && fAscii)
  463. {
  464. RtlCopyMemory(pbBuf, pbSource, cbSize - 1);
  465. ((CHAR *)pbBuf)[cchSize - 1] = '\0';
  466. pVarnt->vt = VT_LPSTR;
  467. pVarnt->pszVal = (PSZ)pbBuf;
  468. }
  469. else
  470. {
  471. if (!fAscii) {
  472. RtlCopyMemory(pbBuf, pbSource, cbSize - sizeof(WCHAR));
  473. } else {
  474. for (unsigned i=0; i<cchSize-1; i++) {
  475. ((WCHAR*)pbBuf)[i] = ((CHAR*)pbSource)[i];
  476. }
  477. }
  478. ((WCHAR *)pbBuf)[cchSize - 1] = L'\0';
  479. pVarnt->vt = VT_LPWSTR;
  480. pVarnt->pwszVal = (PWSTR)pbBuf;
  481. }
  482. return GVRSuccess;
  483. }
  484. //+---------------------------------------------------------------------------
  485. //
  486. // Function: GetData
  487. //
  488. // Synopsis: Copies a NULL terminated string into the pwszStr by looking
  489. // up the string identified by "ulKey".
  490. //
  491. // Arguments: [ulKey] - Key of the string to lookup.
  492. // [pwszStr] - Pointer to the buffer to copy to.
  493. // [cwcStr] - On input, it contains the length of the buffer in
  494. // WCHARs. On output, it has the length of the string
  495. // copied INCLUDING the terminating NULL.
  496. //
  497. // Returns: GVR* code
  498. //
  499. // History: 5-19-95 srikants Created
  500. //
  501. // Notes:
  502. //
  503. //----------------------------------------------------------------------------
  504. GetValueResult
  505. CCompressedColHashString::GetData( ULONG ulKey,
  506. WCHAR * pwszStr,
  507. ULONG & cwcStr
  508. )
  509. {
  510. Win4Assert(ulKey <= _cDataItems);
  511. if (ulKey == 0)
  512. {
  513. return GVRNotAvailable;
  514. }
  515. HashEntry* pData = ((HashEntry*) _pAlloc->FirstRow()) + ulKey - 1;
  516. BOOL fAscii = (pData->usSizeFmt & 1) != 0;
  517. Win4Assert( !fAscii );
  518. ULONG cchSize = (pData->usSizeFmt >> 1) + 1;
  519. ULONG cbSize = cchSize * sizeof (WCHAR);
  520. if ( cwcStr < cchSize )
  521. {
  522. return GVRNotEnoughSpace;
  523. }
  524. BYTE* pbSource = (BYTE*)_pAlloc->OffsetToPointer(pData->ulStringKey);
  525. RtlCopyMemory( pwszStr, pbSource, cbSize - sizeof(WCHAR) );
  526. pwszStr[cchSize - 1] = L'\0';
  527. cwcStr = cchSize;
  528. return GVRSuccess;
  529. }
  530. //+---------------------------------------------------------------------------
  531. //
  532. // Function: GetCountedWStr
  533. //
  534. // Synopsis: Returns a pointer to a string which is NOT null terminated.
  535. // The length of the string (in characters) is returned in
  536. // cwcStr.
  537. //
  538. // Arguments: [ulKey] - String to lookup
  539. // [cwcStr] - OUTPUT - length of the string in WCHARs.
  540. //
  541. // History: 5-19-95 srikants Created
  542. //
  543. // Notes:
  544. //
  545. //----------------------------------------------------------------------------
  546. const WCHAR *
  547. CCompressedColHashString::GetCountedWStr( ULONG ulKey,
  548. ULONG & cwcStr
  549. )
  550. {
  551. Win4Assert(ulKey <= _cDataItems);
  552. if (ulKey == 0)
  553. return 0;
  554. HashEntry* pData = ((HashEntry*) _pAlloc->FirstRow()) + ulKey - 1;
  555. BOOL fAscii = (pData->usSizeFmt & 1) != 0;
  556. Win4Assert( !fAscii );
  557. ULONG cchSize = (pData->usSizeFmt >> 1);
  558. BYTE* pbSource = (BYTE*)_pAlloc->OffsetToPointer(pData->ulStringKey);
  559. Win4Assert( ( (TBL_OFF)pbSource & (TBL_OFF) 0x1 ) == 0 ); // properly aligned on word.
  560. cwcStr = cchSize;
  561. return (const WCHAR *) pbSource;
  562. }
  563. //+-------------------------------------------------------------------------
  564. //
  565. // Method: CCompressedColHashStr::_GetStringBuffer, private
  566. //
  567. // Synopsis: Private helper for the public GetData method. Gets
  568. // a string buffer of sufficient size to accomodate the
  569. // request.
  570. //
  571. // Arguments: [cchString] - number of characters required in buffer
  572. //
  573. // Returns: pointer to a buffer of sufficient size
  574. //
  575. // Notes:
  576. //
  577. // History: 03 Mar 1995 Alanw Created
  578. //
  579. //--------------------------------------------------------------------------
  580. PWSTR CCompressedColHashString::_GetStringBuffer( unsigned cchString )
  581. {
  582. if (! _Buf1.InUse())
  583. return _Buf1.Alloc(cchString);
  584. else if (! _Buf2.InUse())
  585. return _Buf2.Alloc(cchString);
  586. else
  587. return new WCHAR [ cchString ];
  588. }
  589. //+-------------------------------------------------------------------------
  590. //
  591. // Method: CCompressedColHashString::FreeVariant, public
  592. //
  593. // Synopsis: Free private data associated with a variant which had
  594. // been filled in by the GetData method.
  595. //
  596. // Arguments: [pVarnt] - pointer to the variant
  597. //
  598. // Returns: Nothing
  599. //
  600. // Notes:
  601. //
  602. //--------------------------------------------------------------------------
  603. void CCompressedColHashString::FreeVariant(PROPVARIANT * pVarnt)
  604. {
  605. if (pVarnt->vt != VT_EMPTY) {
  606. Win4Assert(pVarnt->vt == VT_LPWSTR || pVarnt->vt == VT_LPSTR);
  607. if (! _Buf1.FreeConditionally( pVarnt->pwszVal ) &&
  608. ! _Buf2.FreeConditionally( pVarnt->pwszVal ) )
  609. {
  610. delete [] pVarnt->pwszVal;
  611. }
  612. pVarnt->pwszVal = 0; // To prevent accidental re-use
  613. }
  614. }
  615. //+-------------------------------------------------------------------------
  616. //
  617. // Method: CCompressedColHashString::DataLength, public
  618. //
  619. // Synopsis: Free private data associated with a variant which had
  620. // been filled in by the GetData method.
  621. //
  622. // Arguments: [kData] - key to the data
  623. //
  624. // Returns: USHORT number of characters in the data item. Includes
  625. // space for a terminating character. Scale
  626. // this by the size of a character for byte count.
  627. //
  628. // Notes:
  629. //
  630. //--------------------------------------------------------------------------
  631. USHORT CCompressedColHashString::DataLength(ULONG kData)
  632. {
  633. if (kData == 0)
  634. return 0;
  635. else
  636. {
  637. HashEntry* pData = ((HashEntry*) _pAlloc->FirstRow()) + kData - 1;
  638. return (pData->usSizeFmt >> 1) + 1;
  639. }
  640. }
  641. //+-------------------------------------------------------------------------
  642. //
  643. // Method: CCompressedColHashString::_GrowHashTable, private
  644. //
  645. // Synopsis: Grow the space allocated to the hash table and data
  646. // items.
  647. //
  648. // Arguments: - none -
  649. //
  650. // Returns: Nothing
  651. //
  652. // Notes: Called to allocate the initial data area. Unlike the
  653. // like-named method in the fixed hash table, this is
  654. // called only for the initial allocation of data. Data
  655. // Items are not re-hashed after being added to the table.
  656. //
  657. //--------------------------------------------------------------------------
  658. const unsigned HASH_TABLE_SIZE = 174; // Minimum hash table size
  659. // avg. chain length is about
  660. // 3 for a one-page table.
  661. // NOTE: should be even to
  662. // assure DWORD allignment of
  663. // fixed data.
  664. VOID CCompressedColHashString::_GrowHashTable( void )
  665. {
  666. int fRehash = FALSE;
  667. _cHashEntries = HASH_TABLE_SIZE;
  668. Win4Assert(_cDataItems == 0 && _pAlloc == NULL); // only called to initialize.
  669. Win4Assert(_cbDataWidth == sizeof (HashEntry));
  670. _pAlloc = new CFixedVarAllocator( TRUE,
  671. TRUE,
  672. _cbDataWidth,
  673. HASH_TABLE_SIZE*sizeof (HASHKEY) );
  674. }