1"""fontTools.misc.textTools.py -- miscellaneous routines."""
2
3
4from __future__ import print_function, division, absolute_import
5from fontTools.misc.py23 import *
6import ast
7import string
8
9
10# alias kept for backward compatibility
11safeEval = ast.literal_eval
12
13
14def readHex(content):
15	"""Convert a list of hex strings to binary data."""
16	return deHexStr(strjoin(chunk for chunk in content if isinstance(chunk, basestring)))
17
18
19def deHexStr(hexdata):
20	"""Convert a hex string to binary data."""
21	hexdata = strjoin(hexdata.split())
22	if len(hexdata) % 2:
23		hexdata = hexdata + "0"
24	data = []
25	for i in range(0, len(hexdata), 2):
26		data.append(bytechr(int(hexdata[i:i+2], 16)))
27	return bytesjoin(data)
28
29
30def hexStr(data):
31	"""Convert binary data to a hex string."""
32	h = string.hexdigits
33	r = ''
34	for c in data:
35		i = byteord(c)
36		r = r + h[(i >> 4) & 0xF] + h[i & 0xF]
37	return r
38
39
40def num2binary(l, bits=32):
41	items = []
42	binary = ""
43	for i in range(bits):
44		if l & 0x1:
45			binary = "1" + binary
46		else:
47			binary = "0" + binary
48		l = l >> 1
49		if not ((i+1) % 8):
50			items.append(binary)
51			binary = ""
52	if binary:
53		items.append(binary)
54	items.reverse()
55	assert l in (0, -1), "number doesn't fit in number of bits"
56	return ' '.join(items)
57
58
59def binary2num(bin):
60	bin = strjoin(bin.split())
61	l = 0
62	for digit in bin:
63		l = l << 1
64		if digit != "0":
65			l = l | 0x1
66	return l
67
68
69def caselessSort(alist):
70	"""Return a sorted copy of a list. If there are only strings
71	in the list, it will not consider case.
72	"""
73
74	try:
75		return sorted(alist, key=lambda a: (a.lower(), a))
76	except TypeError:
77		return sorted(alist)
78
79
80def pad(data, size):
81	r""" Pad byte string 'data' with null bytes until its length is a
82	multiple of 'size'.
83
84	>>> len(pad(b'abcd', 4))
85	4
86	>>> len(pad(b'abcde', 2))
87	6
88	>>> len(pad(b'abcde', 4))
89	8
90	>>> pad(b'abcdef', 4) == b'abcdef\x00\x00'
91	True
92	"""
93	data = tobytes(data)
94	if size > 1:
95		remainder = len(data) % size
96		if remainder:
97			data += b"\0" * (size - remainder)
98	return data
99
100
101if __name__ == "__main__":
102	import doctest, sys
103	sys.exit(doctest.testmod().failed)
104