ucl_swd.ch 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665
  1. /* ucl_swd.c -- sliding window dictionary
  2. This file is part of the UCL data compression library.
  3. Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
  4. All Rights Reserved.
  5. The UCL library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2 of
  8. the License, or (at your option) any later version.
  9. The UCL library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with the UCL library; see the file COPYING.
  15. If not, write to the Free Software Foundation, Inc.,
  16. 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17. Markus F.X.J. Oberhumer
  18. <markus@oberhumer.com>
  19. */
  20. #if (UCL_UINT_MAX < UCL_0xffffffffL)
  21. # error "UCL_UINT_MAX"
  22. #endif
  23. /***********************************************************************
  24. //
  25. ************************************************************************/
  26. #ifndef SWD_N
  27. # define SWD_N N
  28. #endif
  29. #ifndef SWD_F
  30. # define SWD_F F
  31. #endif
  32. #ifndef SWD_THRESHOLD
  33. # define SWD_THRESHOLD THRESHOLD
  34. #endif
  35. /* unsigned type for dictionary access - don't waste memory here */
  36. #if (SWD_N + SWD_F + SWD_F < USHRT_MAX)
  37. typedef unsigned short swd_uint;
  38. # define SWD_UINT_MAX USHRT_MAX
  39. #else
  40. typedef ucl_uint swd_uint;
  41. # define SWD_UINT_MAX UCL_UINT_MAX
  42. #endif
  43. #define SWD_UINT(x) ((swd_uint)(x))
  44. #ifndef SWD_HSIZE
  45. # define SWD_HSIZE 16384
  46. #endif
  47. #ifndef SWD_MAX_CHAIN
  48. # define SWD_MAX_CHAIN 2048
  49. #endif
  50. #if !defined(HEAD3)
  51. #if 1
  52. # define HEAD3(b,p) \
  53. (((0x9f5f*(((((ucl_uint32)b[p]<<5)^b[p+1])<<5)^b[p+2]))>>5) & (SWD_HSIZE-1))
  54. #else
  55. # define HEAD3(b,p) \
  56. (((0x9f5f*(((((ucl_uint32)b[p+2]<<5)^b[p+1])<<5)^b[p]))>>5) & (SWD_HSIZE-1))
  57. #endif
  58. #endif
  59. #if (SWD_THRESHOLD == 1) && !defined(HEAD2)
  60. # if 1 && defined(UCL_UNALIGNED_OK_2)
  61. # define HEAD2(b,p) (* (const ucl_ushortp) &(b[p]))
  62. # else
  63. # define HEAD2(b,p) (b[p] ^ ((unsigned)b[p+1]<<8))
  64. # endif
  65. # define NIL2 SWD_UINT_MAX
  66. #endif
  67. #if defined(__UCL_CHECKER)
  68. /* malloc arrays of the exact size to detect any overrun */
  69. # ifndef SWD_USE_MALLOC
  70. # define SWD_USE_MALLOC
  71. # endif
  72. #endif
  73. typedef struct
  74. {
  75. /* public - "built-in" */
  76. ucl_uint n;
  77. ucl_uint f;
  78. ucl_uint threshold;
  79. /* public - configuration */
  80. ucl_uint max_chain;
  81. ucl_uint nice_length;
  82. ucl_bool use_best_off;
  83. ucl_uint lazy_insert;
  84. /* public - output */
  85. ucl_uint m_len;
  86. ucl_uint m_off;
  87. ucl_uint look;
  88. int b_char;
  89. #if defined(SWD_BEST_OFF)
  90. ucl_uint best_off[ SWD_BEST_OFF ];
  91. #endif
  92. /* semi public */
  93. UCL_COMPRESS_T *c;
  94. ucl_uint m_pos;
  95. #if defined(SWD_BEST_OFF)
  96. ucl_uint best_pos[ SWD_BEST_OFF ];
  97. #endif
  98. /* private */
  99. const ucl_byte *dict;
  100. const ucl_byte *dict_end;
  101. ucl_uint dict_len;
  102. /* private */
  103. ucl_uint ip; /* input pointer (lookahead) */
  104. ucl_uint bp; /* buffer pointer */
  105. ucl_uint rp; /* remove pointer */
  106. ucl_uint b_size;
  107. unsigned char *b_wrap;
  108. ucl_uint node_count;
  109. ucl_uint first_rp;
  110. #if defined(SWD_USE_MALLOC)
  111. unsigned char *b;
  112. swd_uint *head3;
  113. swd_uint *succ3;
  114. swd_uint *best3;
  115. swd_uint *llen3;
  116. #ifdef HEAD2
  117. swd_uint *head2;
  118. #endif
  119. #else
  120. unsigned char b [ SWD_N + SWD_F + SWD_F ];
  121. swd_uint head3 [ SWD_HSIZE ];
  122. swd_uint succ3 [ SWD_N + SWD_F ];
  123. swd_uint best3 [ SWD_N + SWD_F ];
  124. swd_uint llen3 [ SWD_HSIZE ];
  125. #ifdef HEAD2
  126. swd_uint head2 [ UCL_UINT32_C(65536) ];
  127. #endif
  128. #endif
  129. }
  130. ucl_swd_t;
  131. /* Access macro for head3.
  132. * head3[key] may be uninitialized if the list is emtpy,
  133. * but then its value will never be used.
  134. */
  135. #if defined(__UCL_CHECKER)
  136. # define s_head3(s,key) \
  137. ((s->llen3[key] == 0) ? SWD_UINT_MAX : s->head3[key])
  138. #else
  139. # define s_head3(s,key) s->head3[key]
  140. #endif
  141. /***********************************************************************
  142. //
  143. ************************************************************************/
  144. static
  145. void swd_initdict(ucl_swd_t *s, const ucl_byte *dict, ucl_uint dict_len)
  146. {
  147. s->dict = s->dict_end = NULL;
  148. s->dict_len = 0;
  149. if (!dict || dict_len <= 0)
  150. return;
  151. if (dict_len > s->n)
  152. {
  153. dict += dict_len - s->n;
  154. dict_len = s->n;
  155. }
  156. s->dict = dict;
  157. s->dict_len = dict_len;
  158. s->dict_end = dict + dict_len;
  159. ucl_memcpy(s->b,dict,dict_len);
  160. s->ip = dict_len;
  161. }
  162. static
  163. void swd_insertdict(ucl_swd_t *s, ucl_uint node, ucl_uint len)
  164. {
  165. ucl_uint key;
  166. s->node_count = s->n - len;
  167. s->first_rp = node;
  168. while (len-- > 0)
  169. {
  170. key = HEAD3(s->b,node);
  171. s->succ3[node] = s_head3(s,key);
  172. s->head3[key] = SWD_UINT(node);
  173. s->best3[node] = SWD_UINT(s->f + 1);
  174. s->llen3[key]++;
  175. assert(s->llen3[key] <= s->n);
  176. #ifdef HEAD2
  177. key = HEAD2(s->b,node);
  178. s->head2[key] = SWD_UINT(node);
  179. #endif
  180. node++;
  181. }
  182. }
  183. /***********************************************************************
  184. //
  185. ************************************************************************/
  186. static
  187. int swd_init(ucl_swd_t *s, const ucl_byte *dict, ucl_uint dict_len)
  188. {
  189. ucl_uint i = 0;
  190. int c = 0;
  191. if (s->n == 0)
  192. s->n = SWD_N;
  193. if (s->f == 0)
  194. s->f = SWD_F;
  195. s->threshold = SWD_THRESHOLD;
  196. if (s->n > SWD_N || s->f > SWD_F)
  197. return UCL_E_INVALID_ARGUMENT;
  198. #if defined(SWD_USE_MALLOC)
  199. s->b = (unsigned char *) ucl_alloc(s->n + s->f + s->f, 1);
  200. s->head3 = (swd_uint *) ucl_alloc(SWD_HSIZE, sizeof(*s->head3));
  201. s->succ3 = (swd_uint *) ucl_alloc(s->n + s->f, sizeof(*s->succ3));
  202. s->best3 = (swd_uint *) ucl_alloc(s->n + s->f, sizeof(*s->best3));
  203. s->llen3 = (swd_uint *) ucl_alloc(SWD_HSIZE, sizeof(*s->llen3));
  204. if (!s->b || !s->head3 || !s->succ3 || !s->best3 || !s->llen3)
  205. return UCL_E_OUT_OF_MEMORY;
  206. #ifdef HEAD2
  207. s->head2 = (swd_uint *) ucl_alloc(UCL_UINT32_C(65536), sizeof(*s->head2));
  208. if (!s->head2)
  209. return UCL_E_OUT_OF_MEMORY;
  210. #endif
  211. #endif
  212. /* defaults */
  213. s->max_chain = SWD_MAX_CHAIN;
  214. s->nice_length = s->f;
  215. s->use_best_off = 0;
  216. s->lazy_insert = 0;
  217. s->b_size = s->n + s->f;
  218. if (s->b_size + s->f >= SWD_UINT_MAX)
  219. return UCL_E_ERROR;
  220. s->b_wrap = s->b + s->b_size;
  221. s->node_count = s->n;
  222. ucl_memset(s->llen3, 0, sizeof(s->llen3[0]) * SWD_HSIZE);
  223. #ifdef HEAD2
  224. #if 1
  225. ucl_memset(s->head2, 0xff, sizeof(s->head2[0]) * UCL_UINT32_C(65536));
  226. assert(s->head2[0] == NIL2);
  227. #else
  228. for (i = 0; i < UCL_UINT32_C(65536); i++)
  229. s->head2[i] = NIL2;
  230. #endif
  231. #endif
  232. s->ip = 0;
  233. swd_initdict(s,dict,dict_len);
  234. s->bp = s->ip;
  235. s->first_rp = s->ip;
  236. assert(s->ip + s->f <= s->b_size);
  237. #if 1
  238. s->look = (ucl_uint) (s->c->in_end - s->c->ip);
  239. if (s->look > 0)
  240. {
  241. if (s->look > s->f)
  242. s->look = s->f;
  243. ucl_memcpy(&s->b[s->ip],s->c->ip,s->look);
  244. s->c->ip += s->look;
  245. s->ip += s->look;
  246. }
  247. #else
  248. s->look = 0;
  249. while (s->look < s->f)
  250. {
  251. if ((c = getbyte(*(s->c))) < 0)
  252. break;
  253. s->b[s->ip] = UCL_BYTE(c);
  254. s->ip++;
  255. s->look++;
  256. }
  257. #endif
  258. if (s->ip == s->b_size)
  259. s->ip = 0;
  260. if (s->look >= 2 && s->dict_len > 0)
  261. swd_insertdict(s,0,s->dict_len);
  262. s->rp = s->first_rp;
  263. if (s->rp >= s->node_count)
  264. s->rp -= s->node_count;
  265. else
  266. s->rp += s->b_size - s->node_count;
  267. #if defined(__UCL_CHECKER)
  268. /* initialize memory for the first few HEAD3 (if s->ip is not far
  269. * enough ahead to do this job for us). The value doesn't matter. */
  270. if (s->look < 3)
  271. ucl_memset(&s->b[s->bp+s->look],0,3);
  272. #endif
  273. UCL_UNUSED(i);
  274. UCL_UNUSED(c);
  275. return UCL_E_OK;
  276. }
  277. static
  278. void swd_exit(ucl_swd_t *s)
  279. {
  280. #if defined(SWD_USE_MALLOC)
  281. /* free in reverse order of allocations */
  282. #ifdef HEAD2
  283. ucl_free(s->head2); s->head2 = NULL;
  284. #endif
  285. ucl_free(s->llen3); s->llen3 = NULL;
  286. ucl_free(s->best3); s->best3 = NULL;
  287. ucl_free(s->succ3); s->succ3 = NULL;
  288. ucl_free(s->head3); s->head3 = NULL;
  289. ucl_free(s->b); s->b = NULL;
  290. #else
  291. UCL_UNUSED(s);
  292. #endif
  293. }
  294. #define swd_pos2off(s,pos) \
  295. (s->bp > (pos) ? s->bp - (pos) : s->b_size - ((pos) - s->bp))
  296. /***********************************************************************
  297. //
  298. ************************************************************************/
  299. static __inline__
  300. void swd_getbyte(ucl_swd_t *s)
  301. {
  302. int c;
  303. if ((c = getbyte(*(s->c))) < 0)
  304. {
  305. if (s->look > 0)
  306. --s->look;
  307. #if defined(__UCL_CHECKER)
  308. /* initialize memory - value doesn't matter */
  309. s->b[s->ip] = 0;
  310. if (s->ip < s->f)
  311. s->b_wrap[s->ip] = 0;
  312. #endif
  313. }
  314. else
  315. {
  316. s->b[s->ip] = UCL_BYTE(c);
  317. if (s->ip < s->f)
  318. s->b_wrap[s->ip] = UCL_BYTE(c);
  319. }
  320. if (++s->ip == s->b_size)
  321. s->ip = 0;
  322. if (++s->bp == s->b_size)
  323. s->bp = 0;
  324. if (++s->rp == s->b_size)
  325. s->rp = 0;
  326. }
  327. /***********************************************************************
  328. // remove node from lists
  329. ************************************************************************/
  330. static __inline__
  331. void swd_remove_node(ucl_swd_t *s, ucl_uint node)
  332. {
  333. if (s->node_count == 0)
  334. {
  335. ucl_uint key;
  336. #ifdef UCL_DEBUG
  337. if (s->first_rp != UCL_UINT_MAX)
  338. {
  339. if (node != s->first_rp)
  340. printf("Remove %5d: %5d %5d %5d %5d %6d %6d\n",
  341. node, s->rp, s->ip, s->bp, s->first_rp,
  342. s->ip - node, s->ip - s->bp);
  343. assert(node == s->first_rp);
  344. s->first_rp = UCL_UINT_MAX;
  345. }
  346. #endif
  347. key = HEAD3(s->b,node);
  348. assert(s->llen3[key] > 0);
  349. --s->llen3[key];
  350. #ifdef HEAD2
  351. key = HEAD2(s->b,node);
  352. assert(s->head2[key] != NIL2);
  353. if ((ucl_uint) s->head2[key] == node)
  354. s->head2[key] = NIL2;
  355. #endif
  356. }
  357. else
  358. --s->node_count;
  359. }
  360. /***********************************************************************
  361. //
  362. ************************************************************************/
  363. static
  364. void swd_accept(ucl_swd_t *s, ucl_uint n)
  365. {
  366. assert(n <= s->look);
  367. if (n > 0) do
  368. {
  369. ucl_uint key;
  370. swd_remove_node(s,s->rp);
  371. /* add bp into HEAD3 */
  372. key = HEAD3(s->b,s->bp);
  373. s->succ3[s->bp] = s_head3(s,key);
  374. s->head3[key] = SWD_UINT(s->bp);
  375. s->best3[s->bp] = SWD_UINT(s->f + 1);
  376. s->llen3[key]++;
  377. assert(s->llen3[key] <= s->n);
  378. #ifdef HEAD2
  379. /* add bp into HEAD2 */
  380. key = HEAD2(s->b,s->bp);
  381. s->head2[key] = SWD_UINT(s->bp);
  382. #endif
  383. swd_getbyte(s);
  384. } while (--n > 0);
  385. }
  386. /***********************************************************************
  387. //
  388. ************************************************************************/
  389. static
  390. void swd_search(ucl_swd_t *s, ucl_uint node, ucl_uint cnt)
  391. {
  392. #if 0 && defined(__GNUC__) && defined(__i386__)
  393. register const unsigned char *p1 __asm__("%edi");
  394. register const unsigned char *p2 __asm__("%esi");
  395. register const unsigned char *px __asm__("%edx");
  396. #else
  397. const unsigned char *p1;
  398. const unsigned char *p2;
  399. const unsigned char *px;
  400. #endif
  401. ucl_uint m_len = s->m_len;
  402. const unsigned char * b = s->b;
  403. const unsigned char * bp = s->b + s->bp;
  404. const unsigned char * bx = s->b + s->bp + s->look;
  405. unsigned char scan_end1;
  406. assert(s->m_len > 0);
  407. scan_end1 = bp[m_len - 1];
  408. for ( ; cnt-- > 0; node = s->succ3[node])
  409. {
  410. p1 = bp;
  411. p2 = b + node;
  412. px = bx;
  413. assert(m_len < s->look);
  414. if (
  415. #if 1
  416. p2[m_len - 1] == scan_end1 &&
  417. p2[m_len] == p1[m_len] &&
  418. #endif
  419. p2[0] == p1[0] &&
  420. p2[1] == p1[1])
  421. {
  422. ucl_uint i;
  423. assert(ucl_memcmp(bp,&b[node],3) == 0);
  424. #if 0 && defined(UCL_UNALIGNED_OK_4)
  425. p1 += 3; p2 += 3;
  426. while (p1 < px && * (const ucl_uint32p) p1 == * (const ucl_uint32p) p2)
  427. p1 += 4, p2 += 4;
  428. while (p1 < px && *p1 == *p2)
  429. p1 += 1, p2 += 1;
  430. #else
  431. p1 += 2; p2 += 2;
  432. do {} while (++p1 < px && *p1 == *++p2);
  433. #endif
  434. i = p1 - bp;
  435. #ifdef UCL_DEBUG
  436. if (ucl_memcmp(bp,&b[node],i) != 0)
  437. printf("%5ld %5ld %02x%02x %02x%02x\n",
  438. (long)s->bp, (long) node,
  439. bp[0], bp[1], b[node], b[node+1]);
  440. #endif
  441. assert(ucl_memcmp(bp,&b[node],i) == 0);
  442. #if defined(SWD_BEST_OFF)
  443. if (i < SWD_BEST_OFF)
  444. {
  445. if (s->best_pos[i] == 0)
  446. s->best_pos[i] = node + 1;
  447. }
  448. #endif
  449. if (i > m_len)
  450. {
  451. s->m_len = m_len = i;
  452. s->m_pos = node;
  453. if (m_len == s->look)
  454. return;
  455. if (m_len >= s->nice_length)
  456. return;
  457. if (m_len > (ucl_uint) s->best3[node])
  458. return;
  459. scan_end1 = bp[m_len - 1];
  460. }
  461. }
  462. }
  463. }
  464. /***********************************************************************
  465. //
  466. ************************************************************************/
  467. #ifdef HEAD2
  468. static
  469. ucl_bool swd_search2(ucl_swd_t *s)
  470. {
  471. ucl_uint key;
  472. assert(s->look >= 2);
  473. assert(s->m_len > 0);
  474. key = s->head2[ HEAD2(s->b,s->bp) ];
  475. if (key == NIL2)
  476. return 0;
  477. #ifdef UCL_DEBUG
  478. if (ucl_memcmp(&s->b[s->bp],&s->b[key],2) != 0)
  479. printf("%5ld %5ld %02x%02x %02x%02x\n", (long)s->bp, (long)key,
  480. s->b[s->bp], s->b[s->bp+1], s->b[key], s->b[key+1]);
  481. #endif
  482. assert(ucl_memcmp(&s->b[s->bp],&s->b[key],2) == 0);
  483. #if defined(SWD_BEST_OFF)
  484. if (s->best_pos[2] == 0)
  485. s->best_pos[2] = key + 1;
  486. #endif
  487. if (s->m_len < 2)
  488. {
  489. s->m_len = 2;
  490. s->m_pos = key;
  491. }
  492. return 1;
  493. }
  494. #endif
  495. /***********************************************************************
  496. //
  497. ************************************************************************/
  498. static
  499. void swd_findbest(ucl_swd_t *s)
  500. {
  501. ucl_uint key;
  502. ucl_uint cnt, node;
  503. ucl_uint len;
  504. assert(s->m_len > 0);
  505. /* get current head, add bp into HEAD3 */
  506. key = HEAD3(s->b,s->bp);
  507. node = s->succ3[s->bp] = s_head3(s,key);
  508. cnt = s->llen3[key]++;
  509. assert(s->llen3[key] <= s->n + s->f);
  510. if (cnt > s->max_chain && s->max_chain > 0)
  511. cnt = s->max_chain;
  512. s->head3[key] = SWD_UINT(s->bp);
  513. s->b_char = s->b[s->bp];
  514. len = s->m_len;
  515. if (s->m_len >= s->look)
  516. {
  517. if (s->look == 0)
  518. s->b_char = -1;
  519. s->m_off = 0;
  520. s->best3[s->bp] = SWD_UINT(s->f + 1);
  521. }
  522. else
  523. {
  524. #ifdef HEAD2
  525. if (swd_search2(s))
  526. #endif
  527. if (s->look >= 3)
  528. swd_search(s,node,cnt);
  529. if (s->m_len > len)
  530. s->m_off = swd_pos2off(s,s->m_pos);
  531. s->best3[s->bp] = SWD_UINT(s->m_len);
  532. #if defined(SWD_BEST_OFF)
  533. if (s->use_best_off)
  534. {
  535. int i;
  536. for (i = 2; i < SWD_BEST_OFF; i++)
  537. if (s->best_pos[i] > 0)
  538. s->best_off[i] = swd_pos2off(s,s->best_pos[i]-1);
  539. else
  540. s->best_off[i] = 0;
  541. }
  542. #endif
  543. }
  544. swd_remove_node(s,s->rp);
  545. #ifdef HEAD2
  546. /* add bp into HEAD2 */
  547. key = HEAD2(s->b,s->bp);
  548. s->head2[key] = SWD_UINT(s->bp);
  549. #endif
  550. }
  551. #undef HEAD3
  552. #undef HEAD2
  553. #undef s_head3
  554. /*
  555. vi:ts=4:et
  556. */