2 * Base 224 Encoding & Decoding
4 * (c) 2002 Martin Mares <mj@ucw.cz>
6 * The `base-224' encoding transforms general sequences of bytes
7 * to sequences of non-control 8-bit characters (0x20-0xff). Since
8 * 224 and 256 are incompatible bases (there is no k,l: 224^k=256^l)
9 * and we want to avoid lengthy calculations, we cheat a bit:
11 * Each base-224 digit can be represented as a (base-7 digit, base-32 digit)
12 * pair, so we pass the lower 5 bits directly and use a base-7 encoder
13 * for the upper part. We process blocks of 39 bits and encode them
14 * to 5 base-224 digits: we take 5x5 bits as the lower halves and convert
15 * the remaining 14 bits in base-7 (2^14 = 16384 < 16807 = 7^5) to get
16 * the 7 upper parts we need (with a little redundancy). Little endian
17 * ordering is used to make handling of partial blocks easy.
19 * We transform 39 source bits to 40 destination bits, stretching the data
20 * by 1/39 = approx. 2.56%.
22 * This software may be freely distributed and used according to the terms
23 * of the GNU Lesser General Public License.
29 #include "lib/base224.h"
32 encode_block(byte *w, u32 hi, u32 lo)
37 * Splitting of the 39-bit block: [a-e][0-5] are the base-32 digits, *'s are used for base-7.
38 * +----------------+----------------+----------------+----------------+----------------+
39 * +00******e4e3e2e1|e0******d4d3d2d1|d0******c4c3c2c1|c0******b4b3b2b1|b0****a4a3a2a1a0|
40 * +----------------+----------------+----------------+----------------+----------------+
44 w[1] = (lo >> 7) & 0x1f;
45 w[2] = (lo >> 15) & 0x1f;
46 w[3] = (lo >> 23) & 0x1f;
47 w[4] = (lo >> 31) | ((hi << 1) & 0x1e);
48 x = (lo >> 5) & 0x0003
53 DBG("<<< h=%08x l=%08x x=%d", hi, lo, x);
56 w[y] += 0x20 + ((x % 7) << 5);
62 base224_encode(byte *dest, byte *src, uns len)
64 u32 lo=0, hi=0; /* 64-bit buffer accumulating input bits */
65 uns i=0; /* How many source bits do we have buffered */
83 encode_block(w, hi, lo);
90 if (i) /* Partial block */
92 encode_block(w, hi, lo);
93 w += (i+8)/8; /* Just check logarithms if you want to understand */
99 base224_decode(byte *dest, byte *src, uns len)
101 u32 hi=0, lo=0; /* 64-bit buffer accumulating output bits */
102 uns i=0; /* How many bits do we have accumulated */
103 u32 h, l; /* Decoding of the current block */
104 uns x; /* base-7 part of the current block */
114 ASSERT(*src >= 0x20); /* byte 0 */
117 x = (*src++ >> 5) - 1;
121 ASSERT(*src >= 0x20); /* byte 1 */
122 l |= (*src & 0x1f) << 7;
123 x += ((*src++ >> 5) - 1) * 7;
127 ASSERT(*src >= 0x20); /* byte 2 */
128 l |= (*src & 0x1f) << 15;
129 x += ((*src++ >> 5) - 1) * 7*7;
133 ASSERT(*src >= 0x20); /* byte 3 */
134 l |= (*src & 0x1f) << 23;
135 x += ((*src++ >> 5) - 1) * 7*7*7;
139 ASSERT(*src >= 0x20); /* byte 4 */
141 h = (*src & 0x1f) >> 1;
142 x += ((*src++ >> 5) - 1) * 7*7*7*7;
147 l |= ((x & 0x0003) << 5) /* Decode base-7 */
148 | ((x & 0x001c) << 10)
149 | ((x & 0x00e0) << 15)
150 | ((x & 0x0700) << 20);
151 h |= (x & 0x3800) >> 7;
153 DBG("<<< i=%d h=%08x l=%08x x=%d len0=%d", i, h, l, x, len0);
163 lo = (lo >> 8U) | (hi << 24);
176 int main(int argc, char **argv)
179 byte i[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39 };
182 l = base224_encode(o, i, sizeof(i));
183 fwrite(o, 1, l, stdout);
185 l = base224_decode(w, o, l);
186 fwrite(w, 1, l, stdout);
190 byte i[BASE224_OUT_CHUNK*17], o[BASE224_IN_CHUNK*17];
192 while (l = fread(i, 1, sizeof(i), stdin))
194 l = base224_decode(o, i, l);
195 fwrite(o, 1, l, stdout);
200 byte i[BASE224_IN_CHUNK*23], o[BASE224_OUT_CHUNK*23];
202 while (l = fread(i, 1, sizeof(i), stdin))
204 l = base224_encode(o, i, l);
205 fwrite(o, 1, l, stdout);