mercurial/cext/base85.c
changeset 41336 763b45bc4483
parent 39420 91477b123700
child 48810 ed03fffaac30
equal deleted inserted replaced
41335:b81ca9a3f4e4 41336:763b45bc4483
    22 static void b85prep(void)
    22 static void b85prep(void)
    23 {
    23 {
    24 	unsigned i;
    24 	unsigned i;
    25 
    25 
    26 	memset(b85dec, 0, sizeof(b85dec));
    26 	memset(b85dec, 0, sizeof(b85dec));
    27 	for (i = 0; i < sizeof(b85chars); i++)
    27 	for (i = 0; i < sizeof(b85chars); i++) {
    28 		b85dec[(int)(b85chars[i])] = i + 1;
    28 		b85dec[(int)(b85chars[i])] = i + 1;
       
    29 	}
    29 }
    30 }
    30 
    31 
    31 static PyObject *b85encode(PyObject *self, PyObject *args)
    32 static PyObject *b85encode(PyObject *self, PyObject *args)
    32 {
    33 {
    33 	const unsigned char *text;
    34 	const unsigned char *text;
    35 	char *dst;
    36 	char *dst;
    36 	Py_ssize_t len, olen, i;
    37 	Py_ssize_t len, olen, i;
    37 	unsigned int acc, val, ch;
    38 	unsigned int acc, val, ch;
    38 	int pad = 0;
    39 	int pad = 0;
    39 
    40 
    40 	if (!PyArg_ParseTuple(args, PY23("s#|i", "y#|i"), &text, &len, &pad))
    41 	if (!PyArg_ParseTuple(args, PY23("s#|i", "y#|i"), &text, &len, &pad)) {
    41 		return NULL;
    42 		return NULL;
    42 
    43 	}
    43 	if (pad)
    44 
       
    45 	if (pad) {
    44 		olen = ((len + 3) / 4 * 5) - 3;
    46 		olen = ((len + 3) / 4 * 5) - 3;
    45 	else {
    47 	} else {
    46 		olen = len % 4;
    48 		olen = len % 4;
    47 		if (olen)
    49 		if (olen) {
    48 			olen++;
    50 			olen++;
       
    51 		}
    49 		olen += len / 4 * 5;
    52 		olen += len / 4 * 5;
    50 	}
    53 	}
    51 	if (!(out = PyBytes_FromStringAndSize(NULL, olen + 3)))
    54 	if (!(out = PyBytes_FromStringAndSize(NULL, olen + 3))) {
    52 		return NULL;
    55 		return NULL;
       
    56 	}
    53 
    57 
    54 	dst = PyBytes_AsString(out);
    58 	dst = PyBytes_AsString(out);
    55 
    59 
    56 	while (len) {
    60 	while (len) {
    57 		acc = 0;
    61 		acc = 0;
    58 		for (i = 24; i >= 0; i -= 8) {
    62 		for (i = 24; i >= 0; i -= 8) {
    59 			ch = *text++;
    63 			ch = *text++;
    60 			acc |= ch << i;
    64 			acc |= ch << i;
    61 			if (--len == 0)
    65 			if (--len == 0) {
    62 				break;
    66 				break;
       
    67 			}
    63 		}
    68 		}
    64 		for (i = 4; i >= 0; i--) {
    69 		for (i = 4; i >= 0; i--) {
    65 			val = acc % 85;
    70 			val = acc % 85;
    66 			acc /= 85;
    71 			acc /= 85;
    67 			dst[i] = b85chars[val];
    72 			dst[i] = b85chars[val];
    68 		}
    73 		}
    69 		dst += 5;
    74 		dst += 5;
    70 	}
    75 	}
    71 
    76 
    72 	if (!pad)
    77 	if (!pad) {
    73 		_PyBytes_Resize(&out, olen);
    78 		_PyBytes_Resize(&out, olen);
       
    79 	}
    74 
    80 
    75 	return out;
    81 	return out;
    76 }
    82 }
    77 
    83 
    78 static PyObject *b85decode(PyObject *self, PyObject *args)
    84 static PyObject *b85decode(PyObject *self, PyObject *args)
    82 	char *dst;
    88 	char *dst;
    83 	Py_ssize_t len, i, j, olen, cap;
    89 	Py_ssize_t len, i, j, olen, cap;
    84 	int c;
    90 	int c;
    85 	unsigned int acc;
    91 	unsigned int acc;
    86 
    92 
    87 	if (!PyArg_ParseTuple(args, PY23("s#", "y#"), &text, &len))
    93 	if (!PyArg_ParseTuple(args, PY23("s#", "y#"), &text, &len)) {
    88 		return NULL;
    94 		return NULL;
       
    95 	}
    89 
    96 
    90 	olen = len / 5 * 4;
    97 	olen = len / 5 * 4;
    91 	i = len % 5;
    98 	i = len % 5;
    92 	if (i)
    99 	if (i) {
    93 		olen += i - 1;
   100 		olen += i - 1;
    94 	if (!(out = PyBytes_FromStringAndSize(NULL, olen)))
   101 	}
    95 		return NULL;
   102 	if (!(out = PyBytes_FromStringAndSize(NULL, olen))) {
       
   103 		return NULL;
       
   104 	}
    96 
   105 
    97 	dst = PyBytes_AsString(out);
   106 	dst = PyBytes_AsString(out);
    98 
   107 
    99 	i = 0;
   108 	i = 0;
   100 	while (i < len) {
   109 	while (i < len) {
   101 		acc = 0;
   110 		acc = 0;
   102 		cap = len - i - 1;
   111 		cap = len - i - 1;
   103 		if (cap > 4)
   112 		if (cap > 4) {
   104 			cap = 4;
   113 			cap = 4;
       
   114 		}
   105 		for (j = 0; j < cap; i++, j++) {
   115 		for (j = 0; j < cap; i++, j++) {
   106 			c = b85dec[(int)*text++] - 1;
   116 			c = b85dec[(int)*text++] - 1;
   107 			if (c < 0) {
   117 			if (c < 0) {
   108 				PyErr_Format(
   118 				PyErr_Format(
   109 				    PyExc_ValueError,
   119 				    PyExc_ValueError,
   134 			acc += c;
   144 			acc += c;
   135 		}
   145 		}
   136 
   146 
   137 		cap = olen < 4 ? olen : 4;
   147 		cap = olen < 4 ? olen : 4;
   138 		olen -= cap;
   148 		olen -= cap;
   139 		for (j = 0; j < 4 - cap; j++)
   149 		for (j = 0; j < 4 - cap; j++) {
   140 			acc *= 85;
   150 			acc *= 85;
   141 		if (cap && cap < 4)
   151 		}
       
   152 		if (cap && cap < 4) {
   142 			acc += 0xffffff >> (cap - 1) * 8;
   153 			acc += 0xffffff >> (cap - 1) * 8;
       
   154 		}
   143 		for (j = 0; j < cap; j++) {
   155 		for (j = 0; j < cap; j++) {
   144 			acc = (acc << 8) | (acc >> 24);
   156 			acc = (acc << 8) | (acc >> 24);
   145 			*dst++ = acc;
   157 			*dst++ = acc;
   146 		}
   158 		}
   147 	}
   159 	}