git
/
base85.c
133 строки · 2.8 Кб
1#include "git-compat-util.h"2#include "base85.h"3
4#undef DEBUG_855
6#ifdef DEBUG_857#define say(a) fprintf(stderr, a)8#define say1(a,b) fprintf(stderr, a, b)9#define say2(a,b,c) fprintf(stderr, a, b, c)10#else11#define say(a) do { /* nothing */ } while (0)12#define say1(a,b) do { /* nothing */ } while (0)13#define say2(a,b,c) do { /* nothing */ } while (0)14#endif15
16static const char en85[] = {17'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',18'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',19'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',20'U', 'V', 'W', 'X', 'Y', 'Z',21'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',22'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',23'u', 'v', 'w', 'x', 'y', 'z',24'!', '#', '$', '%', '&', '(', ')', '*', '+', '-',25';', '<', '=', '>', '?', '@', '^', '_', '`', '{',26'|', '}', '~'27};28
29static char de85[256];30static void prep_base85(void)31{
32int i;33if (de85['Z'])34return;35for (i = 0; i < ARRAY_SIZE(en85); i++) {36int ch = en85[i];37de85[ch] = i + 1;38}39}
40
41int decode_85(char *dst, const char *buffer, int len)42{
43prep_base85();44
45say2("decode 85 <%.*s>", len / 4 * 5, buffer);46while (len) {47unsigned acc = 0;48int de, cnt = 4;49unsigned char ch;50do {51ch = *buffer++;52de = de85[ch];53if (--de < 0)54return error("invalid base85 alphabet %c", ch);55acc = acc * 85 + de;56} while (--cnt);57ch = *buffer++;58de = de85[ch];59if (--de < 0)60return error("invalid base85 alphabet %c", ch);61/* Detect overflow. */62if (0xffffffff / 85 < acc ||630xffffffff - de < (acc *= 85))64return error("invalid base85 sequence %.5s", buffer-5);65acc += de;66say1(" %08x", acc);67
68cnt = (len < 4) ? len : 4;69len -= cnt;70do {71acc = (acc << 8) | (acc >> 24);72*dst++ = acc;73} while (--cnt);74}75say("\n");76
77return 0;78}
79
80void encode_85(char *buf, const unsigned char *data, int bytes)81{
82say("encode 85");83while (bytes) {84unsigned acc = 0;85int cnt;86for (cnt = 24; cnt >= 0; cnt -= 8) {87unsigned ch = *data++;88acc |= ch << cnt;89if (--bytes == 0)90break;91}92say1(" %08x", acc);93for (cnt = 4; cnt >= 0; cnt--) {94int val = acc % 85;95acc /= 85;96buf[cnt] = en85[val];97}98buf += 5;99}100say("\n");101
102*buf = 0;103}
104
105#ifdef DEBUG_85106int main(int ac, char **av)107{
108char buf[1024];109
110if (!strcmp(av[1], "-e")) {111int len = strlen(av[2]);112encode_85(buf, av[2], len);113if (len <= 26) len = len + 'A' - 1;114else len = len + 'a' - 26 - 1;115printf("encoded: %c%s\n", len, buf);116return 0;117}118if (!strcmp(av[1], "-d")) {119int len = *av[2];120if ('A' <= len && len <= 'Z') len = len - 'A' + 1;121else len = len - 'a' + 26 + 1;122decode_85(buf, av[2]+1, len);123printf("decoded: %.*s\n", len, buf);124return 0;125}126if (!strcmp(av[1], "-t")) {127char t[4] = { -1,-1,-1,-1 };128encode_85(buf, t, 4);129printf("encoded: D%s\n", buf);130return 0;131}132}
133#endif134