123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- """fontTools.misc.textTools.py -- miscellaneous routines."""
- import ast
- import string
- # alias kept for backward compatibility
- safeEval = ast.literal_eval
- class Tag(str):
- @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)
- 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)
|