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