Spaces:
Running
Running
"""fontTools.misc.textTools.py -- miscellaneous routines.""" | |
import ast | |
import string | |
# alias kept for backward compatibility | |
safeEval = ast.literal_eval | |
class Tag(str): | |
def transcode(blob): | |
if isinstance(blob, bytes): | |
blob = blob.decode("latin-1") | |
return blob | |
def __new__(self, content): | |
return str.__new__(self, self.transcode(content)) | |
def __ne__(self, other): | |
return not self.__eq__(other) | |
def __eq__(self, other): | |
return str.__eq__(self, self.transcode(other)) | |
def __hash__(self): | |
return str.__hash__(self) | |
def tobytes(self): | |
return self.encode("latin-1") | |
def readHex(content): | |
"""Convert a list of hex strings to binary data.""" | |
return deHexStr(strjoin(chunk for chunk in content if isinstance(chunk, str))) | |
def deHexStr(hexdata): | |
"""Convert a hex string to binary data.""" | |
hexdata = strjoin(hexdata.split()) | |
if len(hexdata) % 2: | |
hexdata = hexdata + "0" | |
data = [] | |
for i in range(0, len(hexdata), 2): | |
data.append(bytechr(int(hexdata[i : i + 2], 16))) | |
return bytesjoin(data) | |
def hexStr(data): | |
"""Convert binary data to a hex string.""" | |
h = string.hexdigits | |
r = "" | |
for c in data: | |
i = byteord(c) | |
r = r + h[(i >> 4) & 0xF] + h[i & 0xF] | |
return r | |
def num2binary(l, bits=32): | |
items = [] | |
binary = "" | |
for i in range(bits): | |
if l & 0x1: | |
binary = "1" + binary | |
else: | |
binary = "0" + binary | |
l = l >> 1 | |
if not ((i + 1) % 8): | |
items.append(binary) | |
binary = "" | |
if binary: | |
items.append(binary) | |
items.reverse() | |
assert l in (0, -1), "number doesn't fit in number of bits" | |
return " ".join(items) | |
def binary2num(bin): | |
bin = strjoin(bin.split()) | |
l = 0 | |
for digit in bin: | |
l = l << 1 | |
if digit != "0": | |
l = l | 0x1 | |
return l | |
def caselessSort(alist): | |
"""Return a sorted copy of a list. If there are only strings | |
in the list, it will not consider case. | |
""" | |
try: | |
return sorted(alist, key=lambda a: (a.lower(), a)) | |
except TypeError: | |
return sorted(alist) | |
def pad(data, size): | |
r"""Pad byte string 'data' with null bytes until its length is a | |
multiple of 'size'. | |
>>> len(pad(b'abcd', 4)) | |
4 | |
>>> len(pad(b'abcde', 2)) | |
6 | |
>>> len(pad(b'abcde', 4)) | |
8 | |
>>> pad(b'abcdef', 4) == b'abcdef\x00\x00' | |
True | |
""" | |
data = tobytes(data) | |
if size > 1: | |
remainder = len(data) % size | |
if remainder: | |
data += b"\0" * (size - remainder) | |
return data | |
def tostr(s, encoding="ascii", errors="strict"): | |
if not isinstance(s, str): | |
return s.decode(encoding, errors) | |
else: | |
return s | |
def tobytes(s, encoding="ascii", errors="strict"): | |
if isinstance(s, str): | |
return s.encode(encoding, errors) | |
else: | |
return bytes(s) | |
def bytechr(n): | |
return bytes([n]) | |
def byteord(c): | |
return c if isinstance(c, int) else ord(c) | |
def strjoin(iterable, joiner=""): | |
return tostr(joiner).join(iterable) | |
def bytesjoin(iterable, joiner=b""): | |
return tobytes(joiner).join(tobytes(item) for item in iterable) | |
if __name__ == "__main__": | |
import doctest, sys | |
sys.exit(doctest.testmod().failed) | |