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.

1012 lines
26 KiB

  1. /*++
  2. Copyright (c) 1991-1999, Microsoft Corporation All rights reserved.
  3. Module Name:
  4. table.c
  5. Abstract:
  6. This file contains functions necessary to manipulate the various
  7. table structures.
  8. External Routines in this file:
  9. ComputeMBSize
  10. Compute844Size
  11. ComputeCTMapSize
  12. Write844Table
  13. Write844TableMap
  14. WriteCTMapTable
  15. WriteWords
  16. FileWrite
  17. RemoveDuplicate844Levels
  18. Revision History:
  19. 06-14-91 JulieB Created.
  20. --*/
  21. //
  22. // Include Files.
  23. //
  24. #include "nlstrans.h"
  25. //
  26. // Constant Declarations.
  27. //
  28. #define HASH_SIZE 65521 // size of hash table (prime #)
  29. //
  30. // Typedef Declarations.
  31. //
  32. typedef struct hash_object_s
  33. {
  34. PVOID pTable; // ptr to table
  35. struct hash_object_s *pNext; // ptr to next hash node
  36. } CT_HASH_OBJECT, *PCT_HASH_OBJECT;
  37. //
  38. // Forward Declarations.
  39. //
  40. void
  41. RemoveDuplicate844Level2(
  42. P844_ARRAY pArr,
  43. int *pBuf2);
  44. void
  45. RemoveDuplicate844Level3(
  46. P844_ARRAY pArr,
  47. int *pBuf3,
  48. int Size);
  49. PVOID
  50. FindHashTable(
  51. PVOID pTbl,
  52. PCT_HASH_OBJECT *pHashTbl,
  53. int Size);
  54. DWORD
  55. GetHashVal(
  56. PVOID pTbl,
  57. int Size);
  58. void
  59. FreeHashTable(
  60. PCT_HASH_OBJECT *pHashTbl);
  61. //-------------------------------------------------------------------------//
  62. // EXTERNAL ROUTINES //
  63. //-------------------------------------------------------------------------//
  64. ////////////////////////////////////////////////////////////////////////////
  65. //
  66. // ComputeMBSize
  67. //
  68. // This routine returns the size (in words) of the MB, Glyph, and DBCS
  69. // tables.
  70. //
  71. // 07-30-91 JulieB Created.
  72. // 12-10-91 JulieB Modified for new table format.
  73. ////////////////////////////////////////////////////////////////////////////
  74. int ComputeMBSize(
  75. PCODEPAGE pCP)
  76. {
  77. int TblSize; // size of table
  78. int Ctr; // loop counter
  79. register int NumRanges; // number of DBCS ranges
  80. PDBCS_ARRAY pArray; // ptr to DBCS array
  81. //
  82. // Compute static size of table.
  83. //
  84. if (pCP->WriteFlags & F_GLYPH)
  85. {
  86. TblSize = 1 + MB_TABLE_SIZE + (1 + GLYPH_TABLE_SIZE) + 1;
  87. }
  88. else
  89. {
  90. TblSize = 1 + MB_TABLE_SIZE + (1) + 1;
  91. }
  92. //
  93. // Compute size with DBCS tables (if any).
  94. //
  95. NumRanges = pCP->NumDBCSRanges;
  96. if ((NumRanges > 0) && (pCP->WriteFlags & F_DBCS))
  97. {
  98. TblSize += DBCS_OFFSET_SIZE;
  99. pArray = pCP->pDBCS;
  100. for (Ctr = 0; Ctr < NumRanges; Ctr++)
  101. {
  102. TblSize += ((pArray[Ctr]->HighRange -
  103. pArray[Ctr]->LowRange + 1) * DBCS_TABLE_SIZE);
  104. }
  105. }
  106. if (Verbose)
  107. printf(" Complete MB Table Size = %d\n", TblSize);
  108. //
  109. // Return the table size.
  110. //
  111. return (TblSize);
  112. }
  113. ////////////////////////////////////////////////////////////////////////////
  114. //
  115. // Compute844Size
  116. //
  117. // This routine returns the size (in words) of the 8:4:4 WORD or DWORD
  118. // table.
  119. //
  120. // 07-30-91 JulieB Created.
  121. ////////////////////////////////////////////////////////////////////////////
  122. int Compute844Size(
  123. int cbBuf2,
  124. int cbBuf3,
  125. int Size)
  126. {
  127. int TblSize; // size of table
  128. //
  129. // Adjust size of cbBuf2 and cbBuf3 for the two empty levels.
  130. //
  131. cbBuf2++;
  132. cbBuf3++;
  133. //
  134. // Compute size of table.
  135. //
  136. TblSize = TABLE_SIZE_8 +
  137. (TABLE_SIZE_4 * cbBuf2) +
  138. (TABLE_SIZE_4 * cbBuf3 * Size / sizeof(WORD));
  139. if (Verbose)
  140. printf(" 844 Table Size = %d\t\tBuf2 = %d\tBuf3 = %d\n",
  141. TblSize, cbBuf2, cbBuf3);
  142. //
  143. // Return the table size.
  144. //
  145. return (TblSize);
  146. }
  147. ////////////////////////////////////////////////////////////////////////////
  148. //
  149. // ComputeCTMapSize
  150. //
  151. // This routine returns the size of the ctype mapping table.
  152. //
  153. ////////////////////////////////////////////////////////////////////////////
  154. DWORD ComputeCTMapSize(
  155. PCT_MAP pMap)
  156. {
  157. DWORD TblSize; // size of table
  158. //
  159. // Compute size of table.
  160. //
  161. TblSize = sizeof(WORD) + (pMap->Length * sizeof(CT_VALUES));
  162. if (Verbose)
  163. printf(" Mapping Table Size = %d\n", TblSize);
  164. //
  165. // Return the table size.
  166. //
  167. return (TblSize);
  168. }
  169. ////////////////////////////////////////////////////////////////////////////
  170. //
  171. // Write844Table
  172. //
  173. // This routine writes the 8:4:4 WORD table to the output file.
  174. //
  175. // 07-30-91 JulieB Created.
  176. ////////////////////////////////////////////////////////////////////////////
  177. int Write844Table(
  178. FILE *pOutputFile,
  179. P844_ARRAY pArr,
  180. int cbBuf2,
  181. int TblSize,
  182. int Size)
  183. {
  184. WORD EmptyLevel2Offset; // empty level 2 offset
  185. WORD EmptyLevel3Offset; // empty level 3 offset
  186. WORD Pos2; // position array 2
  187. WORD Pos3; // position array 3
  188. WORD PosTemp2 = TABLE_SIZE_4; // position in pTemp2
  189. WORD *pTemp; // temporary storage
  190. PVOID pTemp2; // temporary storage
  191. DWORD Ctr, Ctr2, Ctr3; // loop counters
  192. P844_ARRAY ptr2; // ptr to second array
  193. P844_ARRAY ptr3; // ptr to third array
  194. //
  195. // Need to adjust cbBuf2 for the empty level 2 table.
  196. // TblSize was already adjusted for the empty level tables
  197. // in Compute844Size.
  198. //
  199. cbBuf2++;
  200. //
  201. // Set up the position offsets and the empty second and third level
  202. // table offsets. All Unicode characters that have no mappings will
  203. // point to the empty tables. Grab the first table in the second
  204. // level tables (offset TABLE_SIZE_8 in pTemp) and the first table in
  205. // the third level tables (offset TABLE_SIZE_8 + (cbBuf2 * TABLE_SIZE_4))
  206. // for the empty tables.
  207. //
  208. EmptyLevel2Offset = TABLE_SIZE_8;
  209. Pos2 = EmptyLevel2Offset + TABLE_SIZE_4;
  210. EmptyLevel3Offset = TABLE_SIZE_8 + (cbBuf2 * TABLE_SIZE_4);
  211. Pos3 = EmptyLevel3Offset + (TABLE_SIZE_4 * Size / sizeof(WORD));
  212. //
  213. // Allocate temporary storage buffers.
  214. //
  215. if (AllocateTemp844( &pTemp,
  216. EmptyLevel3Offset,
  217. sizeof(WORD) ))
  218. {
  219. return (1);
  220. }
  221. if (AllocateTemp844( &pTemp2,
  222. TblSize - EmptyLevel3Offset,
  223. Size ))
  224. {
  225. return (1);
  226. }
  227. //
  228. // Set up the empty second level table to point to the empty third
  229. // level table.
  230. //
  231. for (Ctr2 = 0; Ctr2 < TABLE_SIZE_4; Ctr2++)
  232. {
  233. pTemp[EmptyLevel2Offset + Ctr2] = EmptyLevel3Offset;
  234. }
  235. //
  236. // For each entry in the array, copy the appropriate offsets
  237. // to the storage buffer.
  238. //
  239. for (Ctr = 0; Ctr < TABLE_SIZE_8; Ctr++)
  240. {
  241. if ((ptr2 = (P844_ARRAY)(pArr[Ctr])) != NULL)
  242. {
  243. pTemp[Ctr] = Pos2;
  244. for (Ctr2 = 0; Ctr2 < TABLE_SIZE_4; Ctr2++)
  245. {
  246. if ((ptr3 = ptr2[Ctr2]) != NULL)
  247. {
  248. pTemp[Pos2 + Ctr2] = Pos3;
  249. for (Ctr3 = 0; Ctr3 < TABLE_SIZE_4; Ctr3++)
  250. {
  251. memcpy( ((BYTE *)pTemp2) + ((PosTemp2 + Ctr3) * Size),
  252. ((BYTE *)ptr3) + (Ctr3 * Size),
  253. Size );
  254. }
  255. //
  256. // When advancing the Pos3 counter, must compensate
  257. // for the Size (multiply by 2 for DWORD).
  258. //
  259. Pos3 += (TABLE_SIZE_4 * Size / sizeof(WORD));
  260. PosTemp2 += TABLE_SIZE_4;
  261. }
  262. else
  263. {
  264. pTemp[Pos2 + Ctr2] = EmptyLevel3Offset;
  265. }
  266. }
  267. Pos2 += TABLE_SIZE_4;
  268. }
  269. else
  270. {
  271. pTemp[Ctr] = EmptyLevel2Offset;
  272. }
  273. }
  274. //
  275. // Write temp storage buffers to output file.
  276. //
  277. if (FileWrite( pOutputFile,
  278. pTemp,
  279. sizeof(WORD),
  280. Pos2,
  281. "8:4:4 buffer" ))
  282. {
  283. return (1);
  284. }
  285. if (FileWrite( pOutputFile,
  286. pTemp2,
  287. Size,
  288. PosTemp2,
  289. "8:4:4 buffer" ))
  290. {
  291. return (1);
  292. }
  293. //
  294. // Return success.
  295. //
  296. return (0);
  297. }
  298. ////////////////////////////////////////////////////////////////////////////
  299. //
  300. // Write844TableMap
  301. //
  302. // This routine writes the 8:4:4 BYTE "mapped" table to the output file.
  303. //
  304. // 10-29-93 JulieB Created.
  305. ////////////////////////////////////////////////////////////////////////////
  306. int Write844TableMap(
  307. FILE *pOutputFile,
  308. P844_ARRAY pArr,
  309. WORD TblSize)
  310. {
  311. WORD EmptyLevel2Offset; // empty level 2 offset
  312. WORD EmptyLevel3Offset; // empty level 3 offset
  313. WORD Pos; // position level 2 & 3
  314. WORD *pTemp2; // temporary storage - level 2
  315. BYTE *pTempTbl; // temporary storage - entire table
  316. DWORD Ctr, Ctr2, Ctr3; // loop counters
  317. P844_ARRAY ptr2; // ptr to second array
  318. PCT_MAP_VALUE ptr3; // ptr to third array
  319. //
  320. // Set up the second and third level empty tables.
  321. //
  322. EmptyLevel3Offset = (TABLE_SIZE_8 * sizeof(WORD));
  323. EmptyLevel2Offset = EmptyLevel3Offset + (TABLE_SIZE_4 * sizeof(BYTE));
  324. //
  325. // Set up position offset for the regular second and third level
  326. // tables.
  327. //
  328. Pos = EmptyLevel2Offset + (TABLE_SIZE_4 * sizeof(WORD));
  329. //
  330. // Allocate temporary storage buffers.
  331. //
  332. if (AllocateTemp844( &pTemp2,
  333. TABLE_SIZE_4,
  334. sizeof(WORD) ))
  335. {
  336. return (1);
  337. }
  338. if (AllocateTemp844( &pTempTbl,
  339. TblSize,
  340. sizeof(BYTE) ))
  341. {
  342. return (1);
  343. }
  344. //
  345. // Set up the empty second level table to point to the empty third
  346. // level table.
  347. //
  348. for (Ctr = 0; Ctr < TABLE_SIZE_4; Ctr++)
  349. {
  350. pTemp2[Ctr] = EmptyLevel3Offset;
  351. }
  352. memcpy( &pTempTbl[EmptyLevel2Offset],
  353. pTemp2,
  354. TABLE_SIZE_4 * sizeof(WORD) );
  355. //
  356. // For each entry in the array, copy the appropriate offsets
  357. // to the storage buffers.
  358. //
  359. for (Ctr = 0; Ctr < TABLE_SIZE_8; Ctr++)
  360. {
  361. if ((ptr2 = (P844_ARRAY)(pArr[Ctr])) != NULL)
  362. {
  363. //
  364. // See if the table is a duplicate.
  365. //
  366. if (ptr2[DUPLICATE_OFFSET] != 0)
  367. {
  368. //
  369. // Table IS a duplicate, so just save the offset.
  370. //
  371. ((WORD *)pTempTbl)[Ctr] = (WORD)(ptr2[DUPLICATE_OFFSET]);
  372. //
  373. // Set the duplicate pointer to null in the previous level,
  374. // so that freeing of the 844 table is simpler.
  375. //
  376. pArr[Ctr] = NULL;
  377. }
  378. else
  379. {
  380. //
  381. // Table is NOT a duplicate.
  382. // Copy it and save the position for use later if
  383. // it's a duplicate.
  384. //
  385. for (Ctr2 = 0; Ctr2 < TABLE_SIZE_4; Ctr2++)
  386. {
  387. if ((ptr3 = ptr2[Ctr2]) != NULL)
  388. {
  389. //
  390. // See if the table is a duplicate.
  391. //
  392. if (*(WORD *)(ptr3 + DUPLICATE_OFFSET) != 0)
  393. {
  394. //
  395. // Table IS a duplicate, so just save the
  396. // offset.
  397. //
  398. pTemp2[Ctr2] = *(WORD *)(ptr3 + DUPLICATE_OFFSET);
  399. //
  400. // Set the duplicate pointer to null in the
  401. // previous level, so that freeing of the
  402. // 844 table is simpler.
  403. //
  404. ptr2[Ctr2] = NULL;
  405. }
  406. else
  407. {
  408. //
  409. // Table is NOT yet a duplicate.
  410. // Save the position in case this third
  411. // level table is used again.
  412. //
  413. *(WORD *)(ptr3 + DUPLICATE_OFFSET) = Pos;
  414. pTemp2[Ctr2] = Pos;
  415. //
  416. // Copy the third level table to the buffer
  417. // and update the position counter.
  418. //
  419. for (Ctr3 = 0; Ctr3 < TABLE_SIZE_4; Ctr3++)
  420. {
  421. pTempTbl[Pos + Ctr3] = ptr3[Ctr3];
  422. }
  423. Pos += TABLE_SIZE_4;
  424. }
  425. }
  426. else
  427. {
  428. pTemp2[Ctr2] = EmptyLevel3Offset;
  429. }
  430. }
  431. //
  432. // Save the position in case this second level table is
  433. // used again.
  434. //
  435. (WORD)ptr2[DUPLICATE_OFFSET] = Pos;
  436. //
  437. // Copy the second level table to the buffer,
  438. // update the first level table with the position of
  439. // the second level table, and update the position
  440. // counter.
  441. //
  442. memcpy( &pTempTbl[Pos],
  443. pTemp2,
  444. TABLE_SIZE_4 * sizeof(WORD) );
  445. ((WORD *)pTempTbl)[Ctr] = Pos;
  446. Pos += (TABLE_SIZE_4 * sizeof(WORD));
  447. }
  448. }
  449. else
  450. {
  451. ((WORD *)pTempTbl)[Ctr] = EmptyLevel2Offset;
  452. }
  453. }
  454. //
  455. // Write temp storage buffers to output file.
  456. //
  457. if (FileWrite( pOutputFile,
  458. pTempTbl,
  459. sizeof(BYTE),
  460. TblSize,
  461. "8:4:4 buffer" ))
  462. {
  463. return (1);
  464. }
  465. //
  466. // Return success.
  467. //
  468. return (0);
  469. }
  470. ////////////////////////////////////////////////////////////////////////////
  471. //
  472. // WriteCTMapTable
  473. //
  474. // This routine writes the ctype mapping table to the output file.
  475. //
  476. ////////////////////////////////////////////////////////////////////////////
  477. int WriteCTMapTable(
  478. FILE *pOutputFile,
  479. PCT_MAP pMap,
  480. WORD MapSize)
  481. {
  482. //
  483. // Write the size of the mapping table.
  484. //
  485. if (FileWrite( pOutputFile,
  486. &MapSize,
  487. sizeof(WORD),
  488. 1,
  489. "Mapping Table size" ))
  490. {
  491. fclose(pOutputFile);
  492. return (1);
  493. }
  494. //
  495. // Write mapping table to output file.
  496. //
  497. if (FileWrite( pOutputFile,
  498. pMap->pCTValues,
  499. MapSize - sizeof(WORD),
  500. 1,
  501. "Mapping Table buffer" ))
  502. {
  503. return (1);
  504. }
  505. //
  506. // Return success.
  507. //
  508. return (0);
  509. }
  510. ////////////////////////////////////////////////////////////////////////////
  511. //
  512. // WriteWords
  513. //
  514. // This routine writes multiple words of the same value to the output file.
  515. // The number of values written is determined by the Num parameter.
  516. //
  517. // 07-30-91 JulieB Created.
  518. // 12-10-91 JulieB Modified for new table format.
  519. ////////////////////////////////////////////////////////////////////////////
  520. int WriteWords(
  521. FILE *pOutputFile,
  522. WORD Value,
  523. int Num)
  524. {
  525. //
  526. // Write the given 'Value' as a WORD 'Num' times to the output file.
  527. //
  528. if (FileWrite( pOutputFile,
  529. &Value,
  530. sizeof(WORD),
  531. Num,
  532. "WRITE WORDS" ))
  533. {
  534. return (1);
  535. }
  536. //
  537. // Return success.
  538. //
  539. return (0);
  540. }
  541. ////////////////////////////////////////////////////////////////////////////
  542. //
  543. // FileWrite
  544. //
  545. // This routine writes the given buffer to the output file. If an error is
  546. // encountered, then it is returned.
  547. //
  548. // 07-30-91 JulieB Created.
  549. // 12-10-91 JulieB Modified for new table format.
  550. ////////////////////////////////////////////////////////////////////////////
  551. int FileWrite(
  552. FILE *pOutputFile,
  553. void *Buffer,
  554. int Size,
  555. int Count,
  556. char *ErrStr)
  557. {
  558. //
  559. // Write information to output file.
  560. //
  561. if (fwrite( Buffer,
  562. Size,
  563. Count,
  564. pOutputFile ) != (unsigned int)Count)
  565. {
  566. printf("Write Error: Can't write %s to file.\n", ErrStr);
  567. return (1);
  568. }
  569. //
  570. // Return success.
  571. //
  572. return (0);
  573. }
  574. ////////////////////////////////////////////////////////////////////////////
  575. //
  576. // RemoveDuplicate844Levels
  577. //
  578. // This routine removes all duplicate second levels and all duplicate
  579. // third levels from an 8:4:4 table.
  580. //
  581. ////////////////////////////////////////////////////////////////////////////
  582. void RemoveDuplicate844Levels(
  583. P844_ARRAY pArr,
  584. int *pBuf2,
  585. int *pBuf3,
  586. int Size)
  587. {
  588. //
  589. // Remove the duplicates from the third level of the 8:4:4 table
  590. // first.
  591. //
  592. RemoveDuplicate844Level3( pArr,
  593. pBuf3,
  594. Size );
  595. //
  596. // Remove the duplicates from the second level of the 8:4:4 table.
  597. //
  598. RemoveDuplicate844Level2( pArr,
  599. pBuf2 );
  600. }
  601. //-------------------------------------------------------------------------//
  602. // INTERNAL ROUTINES //
  603. //-------------------------------------------------------------------------//
  604. ////////////////////////////////////////////////////////////////////////////
  605. //
  606. // RemoveDuplicate844Level2
  607. //
  608. // This routine removes all duplicate second levels from the given 8:4:4
  609. // table.
  610. //
  611. ////////////////////////////////////////////////////////////////////////////
  612. void RemoveDuplicate844Level2(
  613. P844_ARRAY pArr,
  614. int *pBuf2)
  615. {
  616. P844_ARRAY pTbl2; // ptr to second array
  617. P844_ARRAY pCmp; // ptr to second array to compare
  618. int Ctr, Ctr2, Ctr3; // loop counters
  619. //
  620. // Search through all second level tables. If there is a duplicate,
  621. // fix the affected pointers in the first level table and free the
  622. // duplicate table.
  623. //
  624. for (Ctr = 1; Ctr < TABLE_SIZE_8; Ctr++)
  625. {
  626. if ((pTbl2 = (P844_ARRAY)(pArr[Ctr])) != NULL)
  627. {
  628. //
  629. // See if any of the previous second level tables are the
  630. // same as the current one.
  631. //
  632. for (Ctr2 = Ctr - 1; Ctr2 >= 0; Ctr2--)
  633. {
  634. if ((pCmp = (P844_ARRAY)(pArr[Ctr2])) != NULL)
  635. {
  636. //
  637. // Compare each entry in both tables to see if
  638. // the tables are the same.
  639. //
  640. for (Ctr3 = 0; Ctr3 < TABLE_SIZE_4; Ctr3++)
  641. {
  642. if (pTbl2[Ctr3] != pCmp[Ctr3])
  643. {
  644. break;
  645. }
  646. }
  647. if (Ctr3 == TABLE_SIZE_4)
  648. {
  649. //
  650. // Tables are the same. Fix the pointer
  651. // in the first level table.
  652. //
  653. pArr[Ctr] = pCmp;
  654. //
  655. // Free the duplicate second level table.
  656. //
  657. free(pTbl2);
  658. //
  659. // Decrement the number of second level tables.
  660. //
  661. (*pBuf2)--;
  662. //
  663. // Found the duplicate, so break out of the
  664. // comparison loop.
  665. //
  666. break;
  667. }
  668. }
  669. }
  670. }
  671. }
  672. }
  673. ////////////////////////////////////////////////////////////////////////////
  674. //
  675. // RemoveDuplicate844Level3
  676. //
  677. // This routine removes all duplicate third levels from the given 8:4:4
  678. // table.
  679. //
  680. ////////////////////////////////////////////////////////////////////////////
  681. void RemoveDuplicate844Level3(
  682. P844_ARRAY pArr,
  683. int *pBuf3,
  684. int Size)
  685. {
  686. P844_ARRAY pTbl2; // ptr to second array
  687. PVOID pTbl3; // ptr to third array
  688. PVOID pCmp; // ptr to third array to compare
  689. PCT_HASH_OBJECT *pHashTbl; // hash table
  690. int Ctr, Ctr2; // loop counters
  691. //
  692. // Allocate the hash table.
  693. //
  694. pHashTbl = (PCT_HASH_OBJECT *)malloc(HASH_SIZE * sizeof(PCT_HASH_OBJECT));
  695. memset( pHashTbl,
  696. 0,
  697. (HASH_SIZE * sizeof(PCT_HASH_OBJECT)) );
  698. //
  699. // Search through all third level tables. If there is a duplicate,
  700. // fix the affected pointers in the second level tables and free the
  701. // duplicate table.
  702. //
  703. for (Ctr = 0; Ctr < TABLE_SIZE_8; Ctr++)
  704. {
  705. if ((pTbl2 = (P844_ARRAY)(pArr[Ctr])) != NULL)
  706. {
  707. //
  708. // See if any of the previous third level tables are the
  709. // same as the current one.
  710. //
  711. for (Ctr2 = 0; Ctr2 < TABLE_SIZE_4; Ctr2++)
  712. {
  713. if ((pTbl3 = pTbl2[Ctr2]) != NULL)
  714. {
  715. //
  716. // Compare each entry in the table to see if
  717. // the table is the same as any of the previous
  718. // tables.
  719. //
  720. pCmp = FindHashTable( pTbl3,
  721. pHashTbl,
  722. Size );
  723. if (pCmp != NULL)
  724. {
  725. //
  726. // Tables are the same. Fix the pointer
  727. // in the second level table.
  728. //
  729. pTbl2[Ctr2] = pCmp;
  730. //
  731. // Free the duplicate third level table.
  732. //
  733. free(pTbl3);
  734. //
  735. // Decrement the number of second level tables.
  736. //
  737. (*pBuf3)--;
  738. }
  739. }
  740. }
  741. }
  742. }
  743. //
  744. // Free the hash table.
  745. //
  746. FreeHashTable(pHashTbl);
  747. }
  748. ////////////////////////////////////////////////////////////////////////////
  749. //
  750. // FindHashTable
  751. //
  752. // This routine searches the hash table for the given third level table.
  753. // If a matching table is found, the pointer to the table is returned.
  754. // Otherwise, it returns NULL.
  755. //
  756. ////////////////////////////////////////////////////////////////////////////
  757. PVOID FindHashTable(
  758. PVOID pTbl,
  759. PCT_HASH_OBJECT *pHashTbl,
  760. int Size)
  761. {
  762. DWORD HashVal; // hash value
  763. PCT_HASH_OBJECT pHashN; // ptr to hash node
  764. PCT_HASH_OBJECT pNewHash; // ptr to new hash node
  765. int Ctr; // loop counter
  766. //
  767. // Get hash value of the given table.
  768. //
  769. HashVal = GetHashVal(pTbl, Size);
  770. //
  771. // Search through all hash tables.
  772. //
  773. for (pHashN = pHashTbl[HashVal]; pHashN != NULL; pHashN = pHashN->pNext)
  774. {
  775. //
  776. // See if the two tables are the same. If they are, return the
  777. // pointer to the table.
  778. //
  779. for (Ctr = 0; Ctr < TABLE_SIZE_4; Ctr++)
  780. {
  781. if (memcmp( ((BYTE *)(pHashN->pTable)) + (Ctr * Size),
  782. ((BYTE *)pTbl) + (Ctr * Size),
  783. Size ))
  784. {
  785. break;
  786. }
  787. }
  788. if (Ctr == TABLE_SIZE_4)
  789. {
  790. //
  791. // Tables are the same. Return the pointer to the table.
  792. //
  793. return (pHashN->pTable);
  794. }
  795. }
  796. //
  797. // Could not find a table that matched the given table.
  798. // Create a new hash node and insert it in the hash table.
  799. //
  800. pNewHash = (PCT_HASH_OBJECT)malloc(sizeof(CT_HASH_OBJECT));
  801. pNewHash->pTable = pTbl;
  802. pNewHash->pNext = pHashTbl[HashVal];
  803. pHashTbl[HashVal] = pNewHash;
  804. //
  805. // Return NULL to indicate that an identical table could not be found.
  806. //
  807. return (NULL);
  808. }
  809. ////////////////////////////////////////////////////////////////////////////
  810. //
  811. // GetHashVal
  812. //
  813. // This routine calculates the hash value of a table.
  814. //
  815. ////////////////////////////////////////////////////////////////////////////
  816. DWORD GetHashVal(
  817. PVOID pTbl,
  818. int Size)
  819. {
  820. DWORD HashVal = 0; // hash value
  821. DWORD Multiplier = 1; // multiplier for each entry
  822. int Ctr; // loop counter
  823. for (Ctr = 0; Ctr < TABLE_SIZE_4; Ctr++)
  824. {
  825. HashVal += ((*(((BYTE *)pTbl) + (Ctr * Size))) * Multiplier);
  826. Multiplier *= 2;
  827. }
  828. return ((DWORD)(HashVal / HASH_SIZE));
  829. }
  830. ////////////////////////////////////////////////////////////////////////////
  831. //
  832. // FreeHashTable
  833. //
  834. // This routine frees the hash table.
  835. //
  836. ////////////////////////////////////////////////////////////////////////////
  837. void FreeHashTable(
  838. PCT_HASH_OBJECT *pHashTbl)
  839. {
  840. PCT_HASH_OBJECT pHashN; // ptr to hash node
  841. PCT_HASH_OBJECT pNext; // ptr to next hash node
  842. int Ctr = 0; // loop counter
  843. //
  844. // Search through each entry in the hash table and free each node.
  845. //
  846. for (Ctr = 0; Ctr < HASH_SIZE; Ctr++)
  847. {
  848. pHashN = pHashTbl[Ctr];
  849. while (pHashN != NULL)
  850. {
  851. pNext = pHashN->pNext;
  852. free(pHashN);
  853. pHashN = pNext;
  854. }
  855. }
  856. //
  857. // Free the hash table array.
  858. //
  859. free(pHashTbl);
  860. }