##// END OF EJS Templates
base85: cast Py_ssize_t values to int (issue3481)...
Adrian Buehlmann -
r16848:19a915d4 default
parent child Browse files
Show More
@@ -1,182 +1,185 b''
1 /*
1 /*
2 base85 codec
2 base85 codec
3
3
4 Copyright 2006 Brendan Cully <brendan@kublai.com>
4 Copyright 2006 Brendan Cully <brendan@kublai.com>
5
5
6 This software may be used and distributed according to the terms of
6 This software may be used and distributed according to the terms of
7 the GNU General Public License, incorporated herein by reference.
7 the GNU General Public License, incorporated herein by reference.
8
8
9 Largely based on git's implementation
9 Largely based on git's implementation
10 */
10 */
11
11
12 #define PY_SSIZE_T_CLEAN
12 #define PY_SSIZE_T_CLEAN
13 #include <Python.h>
13 #include <Python.h>
14
14
15 #include "util.h"
15 #include "util.h"
16
16
17 static const char b85chars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
17 static const char b85chars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
18 "abcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~";
18 "abcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~";
19 static char b85dec[256];
19 static char b85dec[256];
20
20
21 static void
21 static void
22 b85prep(void)
22 b85prep(void)
23 {
23 {
24 int i;
24 int 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 static PyObject *
31 static PyObject *
32 b85encode(PyObject *self, PyObject *args)
32 b85encode(PyObject *self, PyObject *args)
33 {
33 {
34 const unsigned char *text;
34 const unsigned char *text;
35 PyObject *out;
35 PyObject *out;
36 char *dst;
36 char *dst;
37 Py_ssize_t len, olen, i;
37 Py_ssize_t len, olen, i;
38 unsigned int acc, val, ch;
38 unsigned int acc, val, ch;
39 int pad = 0;
39 int pad = 0;
40
40
41 if (!PyArg_ParseTuple(args, "s#|i", &text, &len, &pad))
41 if (!PyArg_ParseTuple(args, "s#|i", &text, &len, &pad))
42 return NULL;
42 return NULL;
43
43
44 if (pad)
44 if (pad)
45 olen = ((len + 3) / 4 * 5) - 3;
45 olen = ((len + 3) / 4 * 5) - 3;
46 else {
46 else {
47 olen = len % 4;
47 olen = len % 4;
48 if (olen)
48 if (olen)
49 olen++;
49 olen++;
50 olen += len / 4 * 5;
50 olen += len / 4 * 5;
51 }
51 }
52 if (!(out = PyBytes_FromStringAndSize(NULL, olen + 3)))
52 if (!(out = PyBytes_FromStringAndSize(NULL, olen + 3)))
53 return NULL;
53 return NULL;
54
54
55 dst = PyBytes_AsString(out);
55 dst = PyBytes_AsString(out);
56
56
57 while (len) {
57 while (len) {
58 acc = 0;
58 acc = 0;
59 for (i = 24; i >= 0; i -= 8) {
59 for (i = 24; i >= 0; i -= 8) {
60 ch = *text++;
60 ch = *text++;
61 acc |= ch << i;
61 acc |= ch << i;
62 if (--len == 0)
62 if (--len == 0)
63 break;
63 break;
64 }
64 }
65 for (i = 4; i >= 0; i--) {
65 for (i = 4; i >= 0; i--) {
66 val = acc % 85;
66 val = acc % 85;
67 acc /= 85;
67 acc /= 85;
68 dst[i] = b85chars[val];
68 dst[i] = b85chars[val];
69 }
69 }
70 dst += 5;
70 dst += 5;
71 }
71 }
72
72
73 if (!pad)
73 if (!pad)
74 _PyBytes_Resize(&out, olen);
74 _PyBytes_Resize(&out, olen);
75
75
76 return out;
76 return out;
77 }
77 }
78
78
79 static PyObject *
79 static PyObject *
80 b85decode(PyObject *self, PyObject *args)
80 b85decode(PyObject *self, PyObject *args)
81 {
81 {
82 PyObject *out;
82 PyObject *out;
83 const char *text;
83 const char *text;
84 char *dst;
84 char *dst;
85 Py_ssize_t len, i, j, olen, cap;
85 Py_ssize_t len, i, j, olen, cap;
86 int c;
86 int c;
87 unsigned int acc;
87 unsigned int acc;
88
88
89 if (!PyArg_ParseTuple(args, "s#", &text, &len))
89 if (!PyArg_ParseTuple(args, "s#", &text, &len))
90 return NULL;
90 return NULL;
91
91
92 olen = len / 5 * 4;
92 olen = len / 5 * 4;
93 i = len % 5;
93 i = len % 5;
94 if (i)
94 if (i)
95 olen += i - 1;
95 olen += i - 1;
96 if (!(out = PyBytes_FromStringAndSize(NULL, olen)))
96 if (!(out = PyBytes_FromStringAndSize(NULL, olen)))
97 return NULL;
97 return NULL;
98
98
99 dst = PyBytes_AsString(out);
99 dst = PyBytes_AsString(out);
100
100
101 i = 0;
101 i = 0;
102 while (i < len)
102 while (i < len)
103 {
103 {
104 acc = 0;
104 acc = 0;
105 cap = len - i - 1;
105 cap = len - i - 1;
106 if (cap > 4)
106 if (cap > 4)
107 cap = 4;
107 cap = 4;
108 for (j = 0; j < cap; i++, j++)
108 for (j = 0; j < cap; i++, j++)
109 {
109 {
110 c = b85dec[(int)*text++] - 1;
110 c = b85dec[(int)*text++] - 1;
111 if (c < 0)
111 if (c < 0)
112 return PyErr_Format(
112 return PyErr_Format(
113 PyExc_ValueError,
113 PyExc_ValueError,
114 "bad base85 character at position %d", i);
114 "bad base85 character at position %d",
115 (int)i);
115 acc = acc * 85 + c;
116 acc = acc * 85 + c;
116 }
117 }
117 if (i++ < len)
118 if (i++ < len)
118 {
119 {
119 c = b85dec[(int)*text++] - 1;
120 c = b85dec[(int)*text++] - 1;
120 if (c < 0)
121 if (c < 0)
121 return PyErr_Format(
122 return PyErr_Format(
122 PyExc_ValueError,
123 PyExc_ValueError,
123 "bad base85 character at position %d", i);
124 "bad base85 character at position %d",
125 (int)i);
124 /* overflow detection: 0xffffffff == "|NsC0",
126 /* overflow detection: 0xffffffff == "|NsC0",
125 * "|NsC" == 0x03030303 */
127 * "|NsC" == 0x03030303 */
126 if (acc > 0x03030303 || (acc *= 85) > 0xffffffff - c)
128 if (acc > 0x03030303 || (acc *= 85) > 0xffffffff - c)
127 return PyErr_Format(
129 return PyErr_Format(
128 PyExc_ValueError,
130 PyExc_ValueError,
129 "bad base85 sequence at position %d", i);
131 "bad base85 sequence at position %d",
132 (int)i);
130 acc += c;
133 acc += c;
131 }
134 }
132
135
133 cap = olen < 4 ? olen : 4;
136 cap = olen < 4 ? olen : 4;
134 olen -= cap;
137 olen -= cap;
135 for (j = 0; j < 4 - cap; j++)
138 for (j = 0; j < 4 - cap; j++)
136 acc *= 85;
139 acc *= 85;
137 if (cap && cap < 4)
140 if (cap && cap < 4)
138 acc += 0xffffff >> (cap - 1) * 8;
141 acc += 0xffffff >> (cap - 1) * 8;
139 for (j = 0; j < cap; j++)
142 for (j = 0; j < cap; j++)
140 {
143 {
141 acc = (acc << 8) | (acc >> 24);
144 acc = (acc << 8) | (acc >> 24);
142 *dst++ = acc;
145 *dst++ = acc;
143 }
146 }
144 }
147 }
145
148
146 return out;
149 return out;
147 }
150 }
148
151
149 static char base85_doc[] = "Base85 Data Encoding";
152 static char base85_doc[] = "Base85 Data Encoding";
150
153
151 static PyMethodDef methods[] = {
154 static PyMethodDef methods[] = {
152 {"b85encode", b85encode, METH_VARARGS,
155 {"b85encode", b85encode, METH_VARARGS,
153 "Encode text in base85.\n\n"
156 "Encode text in base85.\n\n"
154 "If the second parameter is true, pad the result to a multiple of "
157 "If the second parameter is true, pad the result to a multiple of "
155 "five characters.\n"},
158 "five characters.\n"},
156 {"b85decode", b85decode, METH_VARARGS, "Decode base85 text.\n"},
159 {"b85decode", b85decode, METH_VARARGS, "Decode base85 text.\n"},
157 {NULL, NULL}
160 {NULL, NULL}
158 };
161 };
159
162
160 #ifdef IS_PY3K
163 #ifdef IS_PY3K
161 static struct PyModuleDef base85_module = {
164 static struct PyModuleDef base85_module = {
162 PyModuleDef_HEAD_INIT,
165 PyModuleDef_HEAD_INIT,
163 "base85",
166 "base85",
164 base85_doc,
167 base85_doc,
165 -1,
168 -1,
166 methods
169 methods
167 };
170 };
168
171
169 PyMODINIT_FUNC PyInit_base85(void)
172 PyMODINIT_FUNC PyInit_base85(void)
170 {
173 {
171 b85prep();
174 b85prep();
172
175
173 return PyModule_Create(&base85_module);
176 return PyModule_Create(&base85_module);
174 }
177 }
175 #else
178 #else
176 PyMODINIT_FUNC initbase85(void)
179 PyMODINIT_FUNC initbase85(void)
177 {
180 {
178 Py_InitModule3("base85", methods, base85_doc);
181 Py_InitModule3("base85", methods, base85_doc);
179
182
180 b85prep();
183 b85prep();
181 }
184 }
182 #endif
185 #endif
General Comments 0
You need to be logged in to leave comments. Login now