• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1"""fontTools.misc.textTools.py -- miscellaneous routines."""
2
3
4import ast
5import string
6
7
8# alias kept for backward compatibility
9safeEval = ast.literal_eval
10
11
12class Tag(str):
13    @staticmethod
14    def transcode(blob):
15        if isinstance(blob, bytes):
16            blob = blob.decode("latin-1")
17        return blob
18
19    def __new__(self, content):
20        return str.__new__(self, self.transcode(content))
21
22    def __ne__(self, other):
23        return not self.__eq__(other)
24
25    def __eq__(self, other):
26        return str.__eq__(self, self.transcode(other))
27
28    def __hash__(self):
29        return str.__hash__(self)
30
31    def tobytes(self):
32        return self.encode("latin-1")
33
34
35def readHex(content):
36	"""Convert a list of hex strings to binary data."""
37	return deHexStr(strjoin(chunk for chunk in content if isinstance(chunk, str)))
38
39
40def deHexStr(hexdata):
41	"""Convert a hex string to binary data."""
42	hexdata = strjoin(hexdata.split())
43	if len(hexdata) % 2:
44		hexdata = hexdata + "0"
45	data = []
46	for i in range(0, len(hexdata), 2):
47		data.append(bytechr(int(hexdata[i:i+2], 16)))
48	return bytesjoin(data)
49
50
51def hexStr(data):
52	"""Convert binary data to a hex string."""
53	h = string.hexdigits
54	r = ''
55	for c in data:
56		i = byteord(c)
57		r = r + h[(i >> 4) & 0xF] + h[i & 0xF]
58	return r
59
60
61def num2binary(l, bits=32):
62	items = []
63	binary = ""
64	for i in range(bits):
65		if l & 0x1:
66			binary = "1" + binary
67		else:
68			binary = "0" + binary
69		l = l >> 1
70		if not ((i+1) % 8):
71			items.append(binary)
72			binary = ""
73	if binary:
74		items.append(binary)
75	items.reverse()
76	assert l in (0, -1), "number doesn't fit in number of bits"
77	return ' '.join(items)
78
79
80def binary2num(bin):
81	bin = strjoin(bin.split())
82	l = 0
83	for digit in bin:
84		l = l << 1
85		if digit != "0":
86			l = l | 0x1
87	return l
88
89
90def caselessSort(alist):
91	"""Return a sorted copy of a list. If there are only strings
92	in the list, it will not consider case.
93	"""
94
95	try:
96		return sorted(alist, key=lambda a: (a.lower(), a))
97	except TypeError:
98		return sorted(alist)
99
100
101def pad(data, size):
102	r""" Pad byte string 'data' with null bytes until its length is a
103	multiple of 'size'.
104
105	>>> len(pad(b'abcd', 4))
106	4
107	>>> len(pad(b'abcde', 2))
108	6
109	>>> len(pad(b'abcde', 4))
110	8
111	>>> pad(b'abcdef', 4) == b'abcdef\x00\x00'
112	True
113	"""
114	data = tobytes(data)
115	if size > 1:
116		remainder = len(data) % size
117		if remainder:
118			data += b"\0" * (size - remainder)
119	return data
120
121
122def tostr(s, encoding="ascii", errors="strict"):
123    if not isinstance(s, str):
124        return s.decode(encoding, errors)
125    else:
126        return s
127
128
129def tobytes(s, encoding="ascii", errors="strict"):
130    if isinstance(s, str):
131        return s.encode(encoding, errors)
132    else:
133        return bytes(s)
134
135
136def bytechr(n):
137    return bytes([n])
138
139
140def byteord(c):
141    return c if isinstance(c, int) else ord(c)
142
143
144def strjoin(iterable, joiner=""):
145    return tostr(joiner).join(iterable)
146
147
148def bytesjoin(iterable, joiner=b""):
149    return tobytes(joiner).join(tobytes(item) for item in iterable)
150
151
152if __name__ == "__main__":
153	import doctest, sys
154	sys.exit(doctest.testmod().failed)
155