##// END OF EJS Templates
Add a base85 codec
Brendan Cully -
r3283:1f2c3983 default
parent child Browse files
Show More
@@ -0,0 +1,132 b''
1 /*
2 base85 codec
3
4 Copyright 2006 Brendan Cully <brendan@kublai.com>
5
6 This software may be used and distributed according to the terms of
7 the GNU General Public License, incorporated herein by reference.
8
9 Largely based on git's implementation
10 */
11
12 #include <Python.h>
13
14 static const char b85chars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
15 "abcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~";
16 static char b85dec[256];
17
18 static void
19 b85prep(void)
20 {
21 int i;
22
23 memset(b85dec, 0, sizeof(b85dec));
24 for (i = 0; i < sizeof(b85chars); i++)
25 b85dec[(int)(b85chars[i])] = i + 1;
26 }
27
28 static PyObject *
29 b85encode(PyObject *self, PyObject *args)
30 {
31 const unsigned char *text;
32 PyObject *out;
33 char *dst;
34 int len, olen, i;
35 unsigned int acc, val, ch;
36
37 if (!PyArg_ParseTuple(args, "s#", &text, &len))
38 return NULL;
39
40 olen = (len + 3) / 4 * 5;
41 if (!(out = PyString_FromStringAndSize(NULL, olen)))
42 return NULL;
43
44 dst = PyString_AS_STRING(out);
45
46 while (len)
47 {
48 acc = 0;
49 for (i = 24; i >= 0; i -= 8) {
50 ch = *text++;
51 acc |= ch << i;
52 if (--len == 0)
53 break;
54 }
55 for (i = 4; i >= 0; i--) {
56 val = acc % 85;
57 acc /= 85;
58 dst[i] = b85chars[val];
59 }
60 dst += 5;
61 }
62
63 return out;
64 }
65
66 static PyObject *
67 b85decode(PyObject *self, PyObject *args)
68 {
69 PyObject *out;
70 const char *text;
71 char *dst;
72 int len, i, j, olen, c;
73 unsigned int acc;
74
75 if (!PyArg_ParseTuple(args, "s#", &text, &len))
76 return NULL;
77
78 olen = (len + 4) / 5 * 4;
79 if (!(out = PyString_FromStringAndSize(NULL, olen)))
80 return NULL;
81
82 dst = PyString_AS_STRING(out);
83
84 for (i = 1; len; i++)
85 {
86 acc = 0;
87 for (j = 0; j < 4 && --len; j++)
88 {
89 c = b85dec[(int)*text++] - 1;
90 if (c < 0)
91 return PyErr_Format(PyExc_ValueError, "Bad base85 character at position %d", i);
92 acc = acc * 85 + c;
93 }
94 if (len--)
95 {
96 c = b85dec[(int)*text++] - 1;
97 if (c < 0)
98 return PyErr_Format(PyExc_ValueError, "Bad base85 character at position %d", i);
99 }
100 else
101 c = 0;
102 /* overflow detection: 0xffffffff == "|NsC0",
103 * "|NsC" == 0x03030303 */
104 if (acc > 0x03030303 || (acc *= 85) > 0xffffffff - c)
105 return PyErr_Format(PyExc_ValueError, "Bad base85 sequence at position %d", i);
106
107 acc += c;
108
109 for (j = 0; j < 4; j++)
110 {
111 acc = (acc << 8) | (acc >> 24);
112 *dst++ = (char)acc;
113 }
114 }
115
116 return out;
117 }
118
119 static char base85_doc[] = "Base85 Data Encoding";
120
121 static PyMethodDef methods[] = {
122 {"b85encode", b85encode, METH_VARARGS, "encode text in base85\n"},
123 {"b85decode", b85decode, METH_VARARGS, "decode base85 text\n"},
124 {NULL, NULL}
125 };
126
127 PyMODINIT_FUNC initbase85(void)
128 {
129 Py_InitModule3("base85", methods, base85_doc);
130
131 b85prep();
132 }
@@ -1,102 +1,103 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 #
2 #
3 # This is the mercurial setup script.
3 # This is the mercurial setup script.
4 #
4 #
5 # './setup.py install', or
5 # './setup.py install', or
6 # './setup.py --help' for more options
6 # './setup.py --help' for more options
7
7
8 import sys
8 import sys
9 if not hasattr(sys, 'version_info') or sys.version_info < (2, 3):
9 if not hasattr(sys, 'version_info') or sys.version_info < (2, 3):
10 raise SystemExit, "Mercurial requires python 2.3 or later."
10 raise SystemExit, "Mercurial requires python 2.3 or later."
11
11
12 import os
12 import os
13 from distutils.core import setup, Extension
13 from distutils.core import setup, Extension
14 from distutils.command.install_data import install_data
14 from distutils.command.install_data import install_data
15
15
16 # mercurial.packagescan must be the first mercurial module imported
16 # mercurial.packagescan must be the first mercurial module imported
17 import mercurial.packagescan
17 import mercurial.packagescan
18 import mercurial.version
18 import mercurial.version
19
19
20 # py2exe needs to be installed to work
20 # py2exe needs to be installed to work
21 try:
21 try:
22 import py2exe
22 import py2exe
23
23
24 # Help py2exe to find win32com.shell
24 # Help py2exe to find win32com.shell
25 try:
25 try:
26 import modulefinder
26 import modulefinder
27 import win32com
27 import win32com
28 for p in win32com.__path__[1:]: # Take the path to win32comext
28 for p in win32com.__path__[1:]: # Take the path to win32comext
29 modulefinder.AddPackagePath("win32com", p)
29 modulefinder.AddPackagePath("win32com", p)
30 pn = "win32com.shell"
30 pn = "win32com.shell"
31 __import__(pn)
31 __import__(pn)
32 m = sys.modules[pn]
32 m = sys.modules[pn]
33 for p in m.__path__[1:]:
33 for p in m.__path__[1:]:
34 modulefinder.AddPackagePath(pn, p)
34 modulefinder.AddPackagePath(pn, p)
35 except ImportError:
35 except ImportError:
36 pass
36 pass
37
37
38 # Due to the use of demandload py2exe is not finding the modules.
38 # Due to the use of demandload py2exe is not finding the modules.
39 # packagescan.getmodules creates a list of modules included in
39 # packagescan.getmodules creates a list of modules included in
40 # the mercurial package plus depdent modules.
40 # the mercurial package plus depdent modules.
41 from py2exe.build_exe import py2exe as build_exe
41 from py2exe.build_exe import py2exe as build_exe
42
42
43 class py2exe_for_demandload(build_exe):
43 class py2exe_for_demandload(build_exe):
44 """ overwrites the py2exe command class for getting the build
44 """ overwrites the py2exe command class for getting the build
45 directory and for setting the 'includes' option."""
45 directory and for setting the 'includes' option."""
46 def initialize_options(self):
46 def initialize_options(self):
47 self.build_lib = None
47 self.build_lib = None
48 build_exe.initialize_options(self)
48 build_exe.initialize_options(self)
49 def finalize_options(self):
49 def finalize_options(self):
50 # Get the build directory, ie. where to search for modules.
50 # Get the build directory, ie. where to search for modules.
51 self.set_undefined_options('build',
51 self.set_undefined_options('build',
52 ('build_lib', 'build_lib'))
52 ('build_lib', 'build_lib'))
53 # Sets the 'includes' option with the list of needed modules
53 # Sets the 'includes' option with the list of needed modules
54 if not self.includes:
54 if not self.includes:
55 self.includes = []
55 self.includes = []
56 else:
56 else:
57 self.includes = self.includes.split(',')
57 self.includes = self.includes.split(',')
58 mercurial.packagescan.scan(self.build_lib, 'mercurial')
58 mercurial.packagescan.scan(self.build_lib, 'mercurial')
59 mercurial.packagescan.scan(self.build_lib, 'mercurial.hgweb')
59 mercurial.packagescan.scan(self.build_lib, 'mercurial.hgweb')
60 mercurial.packagescan.scan(self.build_lib, 'hgext')
60 mercurial.packagescan.scan(self.build_lib, 'hgext')
61 self.includes += mercurial.packagescan.getmodules()
61 self.includes += mercurial.packagescan.getmodules()
62 build_exe.finalize_options(self)
62 build_exe.finalize_options(self)
63 except ImportError:
63 except ImportError:
64 py2exe_for_demandload = None
64 py2exe_for_demandload = None
65
65
66
66
67 # specify version string, otherwise 'hg identify' will be used:
67 # specify version string, otherwise 'hg identify' will be used:
68 version = ''
68 version = ''
69
69
70 class install_package_data(install_data):
70 class install_package_data(install_data):
71 def finalize_options(self):
71 def finalize_options(self):
72 self.set_undefined_options('install',
72 self.set_undefined_options('install',
73 ('install_lib', 'install_dir'))
73 ('install_lib', 'install_dir'))
74 install_data.finalize_options(self)
74 install_data.finalize_options(self)
75
75
76 mercurial.version.remember_version(version)
76 mercurial.version.remember_version(version)
77 cmdclass = {'install_data': install_package_data}
77 cmdclass = {'install_data': install_package_data}
78 py2exe_opts = {}
78 py2exe_opts = {}
79 if py2exe_for_demandload is not None:
79 if py2exe_for_demandload is not None:
80 cmdclass['py2exe'] = py2exe_for_demandload
80 cmdclass['py2exe'] = py2exe_for_demandload
81 py2exe_opts['console'] = ['hg']
81 py2exe_opts['console'] = ['hg']
82
82
83 setup(name='mercurial',
83 setup(name='mercurial',
84 version=mercurial.version.get_version(),
84 version=mercurial.version.get_version(),
85 author='Matt Mackall',
85 author='Matt Mackall',
86 author_email='mpm@selenic.com',
86 author_email='mpm@selenic.com',
87 url='http://selenic.com/mercurial',
87 url='http://selenic.com/mercurial',
88 description='Scalable distributed SCM',
88 description='Scalable distributed SCM',
89 license='GNU GPL',
89 license='GNU GPL',
90 packages=['mercurial', 'mercurial.hgweb', 'hgext'],
90 packages=['mercurial', 'mercurial.hgweb', 'hgext'],
91 ext_modules=[Extension('mercurial.mpatch', ['mercurial/mpatch.c']),
91 ext_modules=[Extension('mercurial.mpatch', ['mercurial/mpatch.c']),
92 Extension('mercurial.bdiff', ['mercurial/bdiff.c'])],
92 Extension('mercurial.bdiff', ['mercurial/bdiff.c']),
93 Extension('mercurial.base85', ['mercurial/base85.c'])],
93 data_files=[(os.path.join('mercurial', root),
94 data_files=[(os.path.join('mercurial', root),
94 [os.path.join(root, file_) for file_ in files])
95 [os.path.join(root, file_) for file_ in files])
95 for root, dirs, files in os.walk('templates')],
96 for root, dirs, files in os.walk('templates')],
96 cmdclass=cmdclass,
97 cmdclass=cmdclass,
97 scripts=['hg', 'hgmerge'],
98 scripts=['hg', 'hgmerge'],
98 options=dict(bdist_mpkg=dict(zipdist=True,
99 options=dict(bdist_mpkg=dict(zipdist=True,
99 license='COPYING',
100 license='COPYING',
100 readme='contrib/macosx/Readme.html',
101 readme='contrib/macosx/Readme.html',
101 welcome='contrib/macosx/Welcome.html')),
102 welcome='contrib/macosx/Welcome.html')),
102 **py2exe_opts)
103 **py2exe_opts)
General Comments 0
You need to be logged in to leave comments. Login now