annotate src/vtx/lh5dec.c @ 805:1ba5f86aeac9 trunk

[svn] - should check data != NULL before clear data->playing.
author yaz
date Mon, 12 Mar 2007 09:12:26 -0700
parents 26ff35aa9b2b
children 33ffac81f4c7
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
749
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
1 /* extractiong lh5 module
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
2 (c) Haruhiko Okumura
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
3 (m) Roman Scherbakov
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
4 */
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
5 #include <stdlib.h>
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
6 #include <stdio.h>
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
7 #include <string.h> /* memmove */
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
8 #include <limits.h>
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
9
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
10 static unsigned short bitbuf;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
11
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
12 #define BITBUFSIZ (CHAR_BIT * sizeof bitbuf)
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
13
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
14 #define DICBIT 13 /* 12(-lh4-) or 13(-lh5-) */
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
15 #define DICSIZ (1L << DICBIT)
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
16 #define MATCHBIT 8 /* bits for MAXMATCH - THRESHOLD */
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
17 #define MAXMATCH 256 /* formerly F (not more than unsigned char_MAX + 1) */
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
18 #define THRESHOLD 3 /* choose optimal value */
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
19 #define NC (UCHAR_MAX + MAXMATCH + 2 - THRESHOLD)
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
20 #define CBIT 9 /* $\lfloor \log_2 NC \rfloor + 1$ */
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
21 #define CODE_BIT 16 /* codeword length */
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
22 #define NP (DICBIT + 1)
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
23 #define NT (CODE_BIT + 3)
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
24 #define PBIT 4 /* smallest integer such that (1U << PBIT) > NP */
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
25 #define TBIT 5 /* smallest integer such that (1U << TBIT) > NT */
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
26 #if NT > NP
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
27 #define NPT NT
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
28 #else
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
29 #define NPT NP
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
30 #endif
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
31
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
32 static unsigned long origsize, compsize;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
33 static unsigned char *in_buf;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
34 static unsigned char *out_buf;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
35
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
36 static unsigned short subbitbuf;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
37 static int bitcount;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
38
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
39 static unsigned short left[2 * NC - 1], right[2 * NC - 1];
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
40 static unsigned char c_len[NC], pt_len[NPT];
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
41 static unsigned short blocksize;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
42
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
43 static unsigned short c_table[4096], pt_table[256];
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
44
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
45 static int j; /* remaining bytes to copy */
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
46
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
47
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
48 static void error(char *msg)
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
49 {
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
50 fprintf(stderr, "libayemu: lh5dec.c: %s\n", msg);
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
51 exit(EXIT_FAILURE);
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
52 }
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
53
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
54 static void fillbuf(int n) /* Shift bitbuf n bits left, read n bits */
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
55 {
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
56 bitbuf <<= n;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
57 while (n > bitcount) {
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
58 bitbuf |= subbitbuf << (n -= bitcount);
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
59 if (compsize != 0) {
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
60 compsize--; subbitbuf = *in_buf++;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
61 } else subbitbuf = 0;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
62 bitcount = CHAR_BIT;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
63 }
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
64 bitbuf |= subbitbuf >> (bitcount -= n);
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
65 }
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
66
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
67 static unsigned short getbits(int n)
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
68 {
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
69 unsigned short x;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
70
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
71 x = bitbuf >> (BITBUFSIZ - n); fillbuf(n);
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
72 return x;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
73 }
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
74
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
75 // make table for decoding
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
76
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
77 static void make_table(int nchar, unsigned char bitlen[], int tablebits, unsigned short table[])
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
78 {
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
79 unsigned short count[17], weight[17], start[18], *p;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
80 unsigned short i, k, len, ch, jutbits, avail, nextcode, mask;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
81
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
82 for (i = 1; i <= 16; i++) count[i] = 0;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
83 for (i = 0; i < nchar; i++) count[bitlen[i]]++;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
84
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
85 start[1] = 0;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
86 for (i = 1; i <= 16; i++)
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
87 start[i + 1] = start[i] + (count[i] << (16 - i));
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
88 if (start[17] != (unsigned short)(1U << 16)) error("Bad table");
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
89
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
90 jutbits = 16 - tablebits;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
91 for (i = 1; i <= tablebits; i++) {
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
92 start[i] >>= jutbits;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
93 weight[i] = 1U << (tablebits - i);
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
94 }
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
95 while (i <= 16) weight[i++] = 1U << (16 - i);
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
96
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
97 i = start[tablebits + 1] >> jutbits;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
98 if (i != (unsigned short)(1U << 16)) {
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
99 k = 1U << tablebits;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
100 while (i != k) table[i++] = 0;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
101 }
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
102
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
103 avail = nchar;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
104 mask = 1U << (15 - tablebits);
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
105 for (ch = 0; ch < nchar; ch++) {
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
106 if ((len = bitlen[ch]) == 0) continue;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
107 nextcode = start[len] + weight[len];
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
108 if (len <= tablebits) {
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
109 for (i = start[len]; i < nextcode; i++) table[i] = ch;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
110 } else {
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
111 k = start[len];
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
112 p = &table[k >> jutbits];
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
113 i = len - tablebits;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
114 while (i != 0) {
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
115 if (*p == 0) {
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
116 right[avail] = left[avail] = 0;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
117 *p = avail++;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
118 }
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
119 if (k & mask) p = &right[*p];
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
120 else p = &left[*p];
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
121 k <<= 1; i--;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
122 }
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
123 *p = ch;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
124 }
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
125 start[len] = nextcode;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
126 }
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
127 }
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
128
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
129 // static Huffman
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
130
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
131 static void read_pt_len(int nn, int nbit, int i_special)
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
132 {
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
133 int i, c, n;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
134 unsigned short mask;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
135
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
136 n = getbits(nbit);
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
137 if (n == 0) {
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
138 c = getbits(nbit);
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
139 for (i = 0; i < nn; i++) pt_len[i] = 0;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
140 for (i = 0; i < 256; i++) pt_table[i] = c;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
141 } else {
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
142 i = 0;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
143 while (i < n) {
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
144 c = bitbuf >> (BITBUFSIZ - 3);
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
145 if (c == 7) {
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
146 mask = 1U << (BITBUFSIZ - 1 - 3);
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
147 while (mask & bitbuf) { mask >>= 1; c++; }
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
148 }
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
149 fillbuf((c < 7) ? 3 : c - 3);
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
150 pt_len[i++] = c;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
151 if (i == i_special) {
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
152 c = getbits(2);
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
153 while (--c >= 0) pt_len[i++] = 0;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
154 }
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
155 }
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
156 while (i < nn) pt_len[i++] = 0;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
157 make_table(nn, pt_len, 8, pt_table);
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
158 }
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
159 }
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
160
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
161 static void read_c_len(void)
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
162 {
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
163 int i, c, n;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
164 unsigned short mask;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
165
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
166 n = getbits(CBIT);
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
167 if (n == 0) {
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
168 c = getbits(CBIT);
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
169 for (i = 0; i < NC; i++) c_len[i] = 0;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
170 for (i = 0; i < 4096; i++) c_table[i] = c;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
171 } else {
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
172 i = 0;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
173 while (i < n) {
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
174 c = pt_table[bitbuf >> (BITBUFSIZ - 8)];
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
175 if (c >= NT) {
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
176 mask = 1U << (BITBUFSIZ - 1 - 8);
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
177 do {
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
178 if (bitbuf & mask) c = right[c];
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
179 else c = left [c];
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
180 mask >>= 1;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
181 } while (c >= NT);
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
182 }
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
183 fillbuf(pt_len[c]);
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
184 if (c <= 2) {
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
185 if (c == 0) c = 1;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
186 else if (c == 1) c = getbits(4) + 3;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
187 else c = getbits(CBIT) + 20;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
188 while (--c >= 0) c_len[i++] = 0;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
189 } else c_len[i++] = c - 2;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
190 }
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
191 while (i < NC) c_len[i++] = 0;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
192 make_table(NC, c_len, 12, c_table);
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
193 }
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
194 }
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
195
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
196
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
197 static unsigned short decode_c(void)
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
198 {
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
199 unsigned short j, mask;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
200
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
201 if (blocksize == 0) {
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
202 blocksize = getbits(16);
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
203 read_pt_len(NT, TBIT, 3);
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
204 read_c_len();
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
205 read_pt_len(NP, PBIT, -1);
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
206 }
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
207 blocksize--;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
208 j = c_table[bitbuf >> (BITBUFSIZ - 12)];
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
209 if (j >= NC) {
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
210 mask = 1U << (BITBUFSIZ - 1 - 12);
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
211 do {
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
212 if (bitbuf & mask) j = right[j];
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
213 else j = left [j];
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
214 mask >>= 1;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
215 } while (j >= NC);
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
216 }
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
217 fillbuf(c_len[j]);
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
218 return j;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
219 }
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
220
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
221
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
222 static unsigned short decode_p(void)
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
223 {
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
224 unsigned short j, mask;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
225
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
226 j = pt_table[bitbuf >> (BITBUFSIZ - 8)];
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
227 if (j >= NP) {
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
228 mask = 1U << (BITBUFSIZ - 1 - 8);
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
229 do {
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
230 if (bitbuf & mask) j = right[j];
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
231 else j = left [j];
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
232 mask >>= 1;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
233 } while (j >= NP);
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
234 }
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
235 fillbuf(pt_len[j]);
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
236 if (j != 0) j = (1U << (j - 1)) + getbits(j - 1);
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
237 return j;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
238 }
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
239
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
240
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
241 static void decode(unsigned short count, unsigned char buffer[])
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
242 {
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
243 static unsigned short i;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
244 unsigned short r, c;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
245
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
246 r = 0;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
247 while (--j >= 0) {
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
248 buffer[r] = buffer[i];
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
249 i = (i + 1) & (DICSIZ - 1);
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
250 if (++r == count) return;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
251 }
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
252 for ( ; ; ) {
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
253 c = decode_c();
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
254 if (c <= UCHAR_MAX) {
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
255 buffer[r] = c & UCHAR_MAX;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
256 if (++r == count) return;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
257 } else {
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
258 j = c - (UCHAR_MAX + 1 - THRESHOLD);
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
259 i = (r - decode_p() - 1) & (DICSIZ - 1);
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
260 while (--j >= 0) {
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
261 buffer[r] = buffer[i];
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
262 i = (i + 1) & (DICSIZ - 1);
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
263 if (++r == count) return;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
264 }
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
265 }
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
266 }
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
267 }
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
268
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
269 void lh5_decode(unsigned char *inp, unsigned char *outp, unsigned long original_size, unsigned long packed_size)
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
270 {
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
271 unsigned short n;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
272 unsigned char *buffer;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
273
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
274 compsize = packed_size;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
275 origsize = original_size;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
276 in_buf = inp;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
277 out_buf = outp;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
278
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
279 buffer = (unsigned char *) malloc(DICSIZ);
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
280 if (!buffer) error ("Out of memory");
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
281
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
282 bitbuf = 0; subbitbuf = 0; bitcount = 0;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
283 fillbuf(BITBUFSIZ);
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
284 blocksize = 0;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
285 j = 0;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
286
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
287 while (origsize != 0) {
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
288 n = (origsize > DICSIZ) ? DICSIZ : (unsigned short)origsize;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
289 decode(n, buffer);
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
290 memmove(out_buf, buffer, n);
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
291 out_buf += n;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
292 origsize -= n;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
293 }
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
294
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
295 if (buffer) free (buffer);
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
296 buffer = NULL;
26ff35aa9b2b [svn] - vtx input plugin based on a submission from Pavel Vymetalek.
nenolod
parents:
diff changeset
297 }