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