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