# 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

    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)