Source code for fontTools.misc.textTools

"""fontTools.misc.textTools.py -- miscellaneous routines."""

import ast
import string


# alias kept for backward compatibility
safeEval = ast.literal_eval


[docs] class Tag(str):
[docs] @staticmethod 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)
[docs] def tobytes(self): return self.encode("latin-1")
[docs] def readHex(content): """Convert a list of hex strings to binary data.""" return deHexStr(strjoin(chunk for chunk in content if isinstance(chunk, str)))
[docs] 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)
[docs] 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
[docs] 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)
[docs] def binary2num(bin): bin = strjoin(bin.split()) l = 0 for digit in bin: l = l << 1 if digit != "0": l = l | 0x1 return l
[docs] 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)
[docs] 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
[docs] def tostr(s, encoding="ascii", errors="strict"): if not isinstance(s, str): return s.decode(encoding, errors) else: return s
[docs] def tobytes(s, encoding="ascii", errors="strict"): if isinstance(s, str): return s.encode(encoding, errors) else: return bytes(s)
[docs] def bytechr(n): return bytes([n])
[docs] def byteord(c): return c if isinstance(c, int) else ord(c)
[docs] def strjoin(iterable, joiner=""): return tostr(joiner).join(iterable)
[docs] 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)