Leaked source code of windows server 2003
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.

350 lines
8.8 KiB

  1. /*
  2. ** lzcommon.c - Routines common to LZ compression / expansion.
  3. **
  4. ** Author: DavidDi
  5. */
  6. // Headers
  7. ///////////
  8. #include "pch.h"
  9. /*
  10. ** bool LZInitTree(void);
  11. **
  12. ** Initializes trees used in LZ compression.
  13. **
  14. ** Arguments: none
  15. **
  16. ** Returns: true/false
  17. **
  18. ** Globals: RightChild[] and Parent[] arrays reset to NIL to begin
  19. ** encoding.
  20. */
  21. BOOL LZInitTree(PLZINFO pLZI)
  22. {
  23. INT i;
  24. /*
  25. ** For i = 0 to RING_BUF_LEN - 1, rightChild[i] and leftChild[i] will be the
  26. ** right and left children of node i. These nodes need not be initialized.
  27. ** Also, parent[i] is the parent of node i. These are initialized to
  28. ** NIL (= N), which stands for 'not used.'
  29. ** For i = 0 to 255, rightChild[RING_BUF_LEN + i + 1] is the root of the tree
  30. ** for strings that begin with character i. These are initialized to NIL.
  31. ** n.b., there are 256 trees.
  32. */
  33. if (!pLZI->rightChild) {
  34. if (!(pLZI->rightChild = (INT*)LocalAlloc(LPTR, (RING_BUF_LEN + 257) * sizeof(INT)))) {
  35. return(FALSE);
  36. }
  37. }
  38. if (!pLZI->leftChild) {
  39. if (!(pLZI->leftChild = (INT*)LocalAlloc(LPTR, (RING_BUF_LEN + 1) * sizeof(INT)))) {
  40. return(FALSE);
  41. }
  42. }
  43. if (!pLZI->parent) {
  44. if (!(pLZI->parent = (INT*)LocalAlloc(LPTR, (RING_BUF_LEN + 1) * sizeof(INT)))) {
  45. return(FALSE);
  46. }
  47. }
  48. for (i = RING_BUF_LEN + 1; i <= RING_BUF_LEN + 256; i++)
  49. pLZI->rightChild[i] = NIL;
  50. for (i = 0; i < RING_BUF_LEN; i++)
  51. pLZI->parent[i] = NIL;
  52. return(TRUE);
  53. }
  54. VOID
  55. LZFreeTree(PLZINFO pLZI)
  56. {
  57. // Sanity check
  58. if (!pLZI) {
  59. return;
  60. }
  61. if (pLZI->rightChild) {
  62. LocalFree((HLOCAL)pLZI->rightChild);
  63. pLZI->rightChild = NULL;
  64. }
  65. if (pLZI->leftChild) {
  66. LocalFree((HLOCAL)pLZI->leftChild);
  67. pLZI->leftChild = NULL;
  68. }
  69. if (pLZI->parent) {
  70. LocalFree((HLOCAL)pLZI->parent);
  71. pLZI->parent = NULL;
  72. }
  73. }
  74. /*
  75. ** void LZInsertNode(int nodeToInsert, BOOL bDoArithmeticInsert);
  76. **
  77. ** Inserts a new tree into the forest. Inserts string of length
  78. ** cbMaxMatchLen, rgbyteRingBuf[r..r + cbMaxMatchLen - 1], into one of the trees
  79. ** (rgbyteRingBuf[r]'th tree).
  80. **
  81. ** Arguments: nodeToInsert - start of string in ring buffer to insert
  82. ** (also, associated tree root)
  83. ** bDoArithmeticInsert - flag for performing regular LZ node
  84. ** insertion or arithmetic encoding node
  85. ** insertion
  86. **
  87. ** Returns: void
  88. **
  89. ** Globals: cbCurMatch - set to length of longest match
  90. ** iCurMatch - set to start index of longest matching string in
  91. ** ring buffer
  92. **
  93. ** N.b., if cbCurMatch == cbMaxMatchLen, we remove the old node in favor of
  94. ** the new one, since the old node will be deleted sooner.
  95. */
  96. VOID LZInsertNode(INT nodeToInsert, BOOL bDoArithmeticInsert, PLZINFO pLZI)
  97. {
  98. INT i, p, cmp, temp;
  99. BYTE FAR *key;
  100. // Sanity check
  101. if (!pLZI) {
  102. return;
  103. }
  104. cmp = 1;
  105. key = pLZI->rgbyteRingBuf + nodeToInsert;
  106. p = RING_BUF_LEN + 1 + key[0];
  107. pLZI->rightChild[nodeToInsert] = pLZI->leftChild[nodeToInsert] = NIL;
  108. pLZI->cbCurMatch = 0;
  109. FOREVER
  110. {
  111. if (cmp >= 0)
  112. {
  113. if (pLZI->rightChild[p] != NIL)
  114. p = pLZI->rightChild[p];
  115. else
  116. {
  117. pLZI->rightChild[p] = nodeToInsert;
  118. pLZI->parent[nodeToInsert] = p;
  119. return;
  120. }
  121. }
  122. else
  123. {
  124. if (pLZI->leftChild[p] != NIL)
  125. p = pLZI->leftChild[p];
  126. else
  127. {
  128. pLZI->leftChild[p] = nodeToInsert;
  129. pLZI->parent[nodeToInsert] = p;
  130. return;
  131. }
  132. }
  133. for (i = 1; i < pLZI->cbMaxMatchLen; i++)
  134. if ((cmp = key[i] - pLZI->rgbyteRingBuf[p + i]) != 0)
  135. break;
  136. if (bDoArithmeticInsert == TRUE)
  137. {
  138. // Do node insertion for arithmetic encoding.
  139. if (i > MAX_LITERAL_LEN)
  140. {
  141. if (i > pLZI->cbCurMatch)
  142. {
  143. pLZI->iCurMatch = (nodeToInsert - p) & (RING_BUF_LEN - 1);
  144. if ((pLZI->cbCurMatch = i) >= pLZI->cbMaxMatchLen)
  145. break;
  146. }
  147. else if (i == pLZI->cbCurMatch)
  148. {
  149. if ((temp = (nodeToInsert - p) & (RING_BUF_LEN - 1)) < pLZI->iCurMatch)
  150. pLZI->iCurMatch = temp;
  151. }
  152. }
  153. }
  154. else
  155. {
  156. // Do node insertion for LZ.
  157. if (i > pLZI->cbCurMatch)
  158. {
  159. pLZI->iCurMatch = p;
  160. if ((pLZI->cbCurMatch = i) >= pLZI->cbMaxMatchLen)
  161. break;
  162. }
  163. }
  164. }
  165. pLZI->parent[nodeToInsert] = pLZI->parent[p];
  166. pLZI->leftChild[nodeToInsert] = pLZI->leftChild[p];
  167. pLZI->rightChild[nodeToInsert] = pLZI->rightChild[p];
  168. pLZI->parent[pLZI->leftChild[p]] = nodeToInsert;
  169. pLZI->parent[pLZI->rightChild[p]] = nodeToInsert;
  170. if (pLZI->rightChild[pLZI->parent[p]] == p)
  171. pLZI->rightChild[pLZI->parent[p]] = nodeToInsert;
  172. else
  173. pLZI->leftChild[pLZI->parent[p]] = nodeToInsert;
  174. // Remove p.
  175. pLZI->parent[p] = NIL;
  176. return;
  177. }
  178. /*
  179. ** void LZDeleteNode(int nodeToDelete);
  180. **
  181. ** Delete a tree from the forest.
  182. **
  183. ** Arguments: nodeToDelete - tree to delete from forest
  184. **
  185. ** Returns: void
  186. **
  187. ** Globals: Parent[], RightChild[], and LeftChild[] updated to reflect the
  188. ** deletion of nodeToDelete.
  189. */
  190. VOID LZDeleteNode(INT nodeToDelete, PLZINFO pLZI)
  191. {
  192. INT q;
  193. // Sanity check
  194. if (!pLZI) {
  195. return;
  196. }
  197. if (pLZI->parent[nodeToDelete] == NIL)
  198. // Tree nodeToDelete is not in the forest.
  199. return;
  200. if (pLZI->rightChild[nodeToDelete] == NIL)
  201. q = pLZI->leftChild[nodeToDelete];
  202. else if (pLZI->leftChild[nodeToDelete] == NIL)
  203. q = pLZI->rightChild[nodeToDelete];
  204. else
  205. {
  206. q = pLZI->leftChild[nodeToDelete];
  207. if (pLZI->rightChild[q] != NIL)
  208. {
  209. do
  210. {
  211. q = pLZI->rightChild[q];
  212. } while (pLZI->rightChild[q] != NIL);
  213. pLZI->rightChild[pLZI->parent[q]] = pLZI->leftChild[q];
  214. pLZI->parent[pLZI->leftChild[q]] = pLZI->parent[q];
  215. pLZI->leftChild[q] = pLZI->leftChild[nodeToDelete];
  216. pLZI->parent[pLZI->leftChild[nodeToDelete]] = q;
  217. }
  218. pLZI->rightChild[q] = pLZI->rightChild[nodeToDelete];
  219. pLZI->parent[pLZI->rightChild[nodeToDelete]] = q;
  220. }
  221. pLZI->parent[q] = pLZI->parent[nodeToDelete];
  222. if (pLZI->rightChild[pLZI->parent[nodeToDelete]] == nodeToDelete)
  223. pLZI->rightChild[pLZI->parent[nodeToDelete]] = q;
  224. else
  225. pLZI->leftChild[pLZI->parent[nodeToDelete]] = q;
  226. // Remove nodeToDelete.
  227. pLZI->parent[nodeToDelete] = NIL;
  228. return;
  229. }
  230. //these are additional functions required by both diamond.c and compress.c
  231. WCHAR
  232. MakeCompressedNameW(
  233. LPWSTR pszFileName)
  234. /*++
  235. Routine Description: Returns the last character that is stripped out and also
  236. changes the pszFilename
  237. --*/
  238. {
  239. WCHAR chReplaced = L'\0';
  240. WCHAR ARG_PTR *pszExt;
  241. if ((pszExt = ExtractExtensionW(pszFileName)) != NULL)
  242. {
  243. if (lstrlenW(pszExt) >= 3)
  244. {
  245. chReplaced = pszExt[lstrlenW(pszExt) - 1];
  246. pszExt[lstrlenW(pszExt) - 1] = chEXTENSION_CHARW;
  247. }
  248. else
  249. lstrcatW(pszExt, pszEXTENSION_STRW);
  250. }
  251. else
  252. lstrcatW(pszFileName, pszNULL_EXTENSIONW);
  253. return(chReplaced);
  254. }
  255. LPWSTR
  256. ExtractExtensionW(
  257. LPWSTR pszFileName)
  258. /*
  259. char ARG_PTR *ExtractExtension(char ARG_PTR *pszFileName);
  260. Find the extension of a file name.
  261. Arguments: pszFileName - file name to examine
  262. Returns: char ARG_PTR * - Pointer to file name extension if one exists.
  263. NULL if the file name doesn't include an
  264. extension.
  265. */
  266. {
  267. WCHAR *psz;
  268. // Make sure we have an isolated file name.
  269. psz = ExtractFileNameW(pszFileName);
  270. while (*psz != L'\0' && *psz != L'.')
  271. psz++;
  272. if (*psz == L'.')
  273. return(psz + 1);
  274. else
  275. return(NULL);
  276. }
  277. LPWSTR
  278. ExtractFileNameW(
  279. LPWSTR pszPathName)
  280. /*++
  281. Find the file name in a fully specified path name.
  282. Arguments: pszPathName - path string from which to extract file name
  283. Returns: char ARG_PTR * - Pointer to file name in pszPathName.
  284. Globals: none
  285. --*/
  286. {
  287. LPWSTR pszLastComponent, psz;
  288. for (pszLastComponent = psz = pszPathName; *psz != L'\0'; psz++)
  289. {
  290. if (*psz == L'\\' || *psz == L':')
  291. pszLastComponent = psz + 1;
  292. }
  293. return(pszLastComponent);
  294. }