| 1 | /* |
| 2 | * basE91 encoding/decoding routines |
| 3 | * |
| 4 | * Copyright (c) 2000-2006 Joachim Henke |
| 5 | * All rights reserved. |
| 6 | * |
| 7 | * Redistribution and use in source and binary forms, with or without |
| 8 | * modification, are permitted provided that the following conditions are met: |
| 9 | * |
| 10 | * - Redistributions of source code must retain the above copyright notice, |
| 11 | * this list of conditions and the following disclaimer. |
| 12 | * - Redistributions in binary form must reproduce the above copyright notice, |
| 13 | * this list of conditions and the following disclaimer in the documentation |
| 14 | * and/or other materials provided with the distribution. |
| 15 | * - Neither the name of Joachim Henke nor the names of his contributors may |
| 16 | * be used to endorse or promote products derived from this software without |
| 17 | * specific prior written permission. |
| 18 | * |
| 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
| 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| 29 | * POSSIBILITY OF SUCH DAMAGE. |
| 30 | */ |
| 31 | |
| 32 | #include "base91.h" |
| 33 | |
| 34 | const unsigned char enctab[91] = { |
| 35 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', |
| 36 | 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', |
| 37 | 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', |
| 38 | 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', |
| 39 | '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '!', '#', '$', |
| 40 | '%', '&', '(', ')', '*', '+', ',', '.', '/', ':', ';', '<', '=', |
| 41 | '>', '?', '@', '[', ']', '^', '_', '`', '{', '|', '}', '~', '"' |
| 42 | }; |
| 43 | const unsigned char dectab[256] = { |
| 44 | 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, |
| 45 | 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, |
| 46 | 91, 62, 90, 63, 64, 65, 66, 91, 67, 68, 69, 70, 71, 91, 72, 73, |
| 47 | 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 74, 75, 76, 77, 78, 79, |
| 48 | 80, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, |
| 49 | 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 81, 91, 82, 83, 84, |
| 50 | 85, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, |
| 51 | 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 86, 87, 88, 89, 91, |
| 52 | 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, |
| 53 | 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, |
| 54 | 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, |
| 55 | 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, |
| 56 | 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, |
| 57 | 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, |
| 58 | 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, |
| 59 | 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91 |
| 60 | }; |
| 61 | |
| 62 | void basE91_init(struct basE91 *b) |
| 63 | { |
| 64 | b->queue = 0; |
| 65 | b->nbits = 0; |
| 66 | b->val = -1; |
| 67 | } |
| 68 | |
| 69 | size_t basE91_encode(struct basE91 *b, const void *i, size_t len, void *o) |
| 70 | { |
| 71 | const unsigned char *ib = i; |
| 72 | unsigned char *ob = o; |
| 73 | size_t n = 0; |
| 74 | |
| 75 | while (len--) { |
| 76 | b->queue |= *ib++ << b->nbits; |
| 77 | b->nbits += 8; |
| 78 | if (b->nbits > 13) { /* enough bits in queue */ |
| 79 | unsigned int val = b->queue & 8191; |
| 80 | |
| 81 | if (val > 88) { |
| 82 | b->queue >>= 13; |
| 83 | b->nbits -= 13; |
| 84 | } else { /* we can take 14 bits */ |
| 85 | val = b->queue & 16383; |
| 86 | b->queue >>= 14; |
| 87 | b->nbits -= 14; |
| 88 | } |
| 89 | ob[n++] = enctab[val % 91]; |
| 90 | ob[n++] = enctab[val / 91]; |
| 91 | } |
| 92 | } |
| 93 | |
| 94 | return n; |
| 95 | } |
| 96 | |
| 97 | /* process remaining bits from bit queue; write up to 2 bytes */ |
| 98 | |
| 99 | size_t basE91_encode_end(struct basE91 *b, void *o) |
| 100 | { |
| 101 | unsigned char *ob = o; |
| 102 | size_t n = 0; |
| 103 | |
| 104 | if (b->nbits) { |
| 105 | ob[n++] = enctab[b->queue % 91]; |
| 106 | if (b->nbits > 7 || b->queue > 90) |
| 107 | ob[n++] = enctab[b->queue / 91]; |
| 108 | } |
| 109 | b->queue = 0; |
| 110 | b->nbits = 0; |
| 111 | b->val = -1; |
| 112 | |
| 113 | return n; |
| 114 | } |
| 115 | |
| 116 | size_t basE91_decode(struct basE91 *b, const void *i, size_t len, void *o) |
| 117 | { |
| 118 | const unsigned char *ib = i; |
| 119 | unsigned char *ob = o; |
| 120 | size_t n = 0; |
| 121 | unsigned int d; |
| 122 | |
| 123 | while (len--) { |
| 124 | d = dectab[*ib++]; |
| 125 | if (d == 91) |
| 126 | continue; /* ignore non-alphabet chars */ |
| 127 | if (b->val == -1) |
| 128 | b->val = d; /* start next value */ |
| 129 | else { |
| 130 | b->val += d * 91; |
| 131 | b->queue |= b->val << b->nbits; |
| 132 | b->nbits += (b->val & 8191) > 88 ? 13 : 14; |
| 133 | do { |
| 134 | ob[n++] = b->queue; |
| 135 | b->queue >>= 8; |
| 136 | b->nbits -= 8; |
| 137 | } while (b->nbits > 7); |
| 138 | b->val = -1; /* mark value complete */ |
| 139 | } |
| 140 | } |
| 141 | |
| 142 | return n; |
| 143 | } |
| 144 | |
| 145 | /* process remaining bits; write at most 1 byte */ |
| 146 | |
| 147 | size_t basE91_decode_end(struct basE91 *b, void *o) |
| 148 | { |
| 149 | unsigned char *ob = o; |
| 150 | size_t n = 0; |
| 151 | |
| 152 | if (b->val != -1) |
| 153 | ob[n++] = b->queue | b->val << b->nbits; |
| 154 | b->queue = 0; |
| 155 | b->nbits = 0; |
| 156 | b->val = -1; |
| 157 | |
| 158 | return n; |
| 159 | } |