xref: /aosp_15_r20/external/fonttools/Lib/fontTools/misc/textTools.py (revision e1fe3e4ad2793916b15cccdc4a7da52a7e1dd0e9)
1*e1fe3e4aSElliott Hughes"""fontTools.misc.textTools.py -- miscellaneous routines."""
2*e1fe3e4aSElliott Hughes
3*e1fe3e4aSElliott Hughesimport ast
4*e1fe3e4aSElliott Hughesimport string
5*e1fe3e4aSElliott Hughes
6*e1fe3e4aSElliott Hughes
7*e1fe3e4aSElliott Hughes# alias kept for backward compatibility
8*e1fe3e4aSElliott HughessafeEval = ast.literal_eval
9*e1fe3e4aSElliott Hughes
10*e1fe3e4aSElliott Hughes
11*e1fe3e4aSElliott Hughesclass Tag(str):
12*e1fe3e4aSElliott Hughes    @staticmethod
13*e1fe3e4aSElliott Hughes    def transcode(blob):
14*e1fe3e4aSElliott Hughes        if isinstance(blob, bytes):
15*e1fe3e4aSElliott Hughes            blob = blob.decode("latin-1")
16*e1fe3e4aSElliott Hughes        return blob
17*e1fe3e4aSElliott Hughes
18*e1fe3e4aSElliott Hughes    def __new__(self, content):
19*e1fe3e4aSElliott Hughes        return str.__new__(self, self.transcode(content))
20*e1fe3e4aSElliott Hughes
21*e1fe3e4aSElliott Hughes    def __ne__(self, other):
22*e1fe3e4aSElliott Hughes        return not self.__eq__(other)
23*e1fe3e4aSElliott Hughes
24*e1fe3e4aSElliott Hughes    def __eq__(self, other):
25*e1fe3e4aSElliott Hughes        return str.__eq__(self, self.transcode(other))
26*e1fe3e4aSElliott Hughes
27*e1fe3e4aSElliott Hughes    def __hash__(self):
28*e1fe3e4aSElliott Hughes        return str.__hash__(self)
29*e1fe3e4aSElliott Hughes
30*e1fe3e4aSElliott Hughes    def tobytes(self):
31*e1fe3e4aSElliott Hughes        return self.encode("latin-1")
32*e1fe3e4aSElliott Hughes
33*e1fe3e4aSElliott Hughes
34*e1fe3e4aSElliott Hughesdef readHex(content):
35*e1fe3e4aSElliott Hughes    """Convert a list of hex strings to binary data."""
36*e1fe3e4aSElliott Hughes    return deHexStr(strjoin(chunk for chunk in content if isinstance(chunk, str)))
37*e1fe3e4aSElliott Hughes
38*e1fe3e4aSElliott Hughes
39*e1fe3e4aSElliott Hughesdef deHexStr(hexdata):
40*e1fe3e4aSElliott Hughes    """Convert a hex string to binary data."""
41*e1fe3e4aSElliott Hughes    hexdata = strjoin(hexdata.split())
42*e1fe3e4aSElliott Hughes    if len(hexdata) % 2:
43*e1fe3e4aSElliott Hughes        hexdata = hexdata + "0"
44*e1fe3e4aSElliott Hughes    data = []
45*e1fe3e4aSElliott Hughes    for i in range(0, len(hexdata), 2):
46*e1fe3e4aSElliott Hughes        data.append(bytechr(int(hexdata[i : i + 2], 16)))
47*e1fe3e4aSElliott Hughes    return bytesjoin(data)
48*e1fe3e4aSElliott Hughes
49*e1fe3e4aSElliott Hughes
50*e1fe3e4aSElliott Hughesdef hexStr(data):
51*e1fe3e4aSElliott Hughes    """Convert binary data to a hex string."""
52*e1fe3e4aSElliott Hughes    h = string.hexdigits
53*e1fe3e4aSElliott Hughes    r = ""
54*e1fe3e4aSElliott Hughes    for c in data:
55*e1fe3e4aSElliott Hughes        i = byteord(c)
56*e1fe3e4aSElliott Hughes        r = r + h[(i >> 4) & 0xF] + h[i & 0xF]
57*e1fe3e4aSElliott Hughes    return r
58*e1fe3e4aSElliott Hughes
59*e1fe3e4aSElliott Hughes
60*e1fe3e4aSElliott Hughesdef num2binary(l, bits=32):
61*e1fe3e4aSElliott Hughes    items = []
62*e1fe3e4aSElliott Hughes    binary = ""
63*e1fe3e4aSElliott Hughes    for i in range(bits):
64*e1fe3e4aSElliott Hughes        if l & 0x1:
65*e1fe3e4aSElliott Hughes            binary = "1" + binary
66*e1fe3e4aSElliott Hughes        else:
67*e1fe3e4aSElliott Hughes            binary = "0" + binary
68*e1fe3e4aSElliott Hughes        l = l >> 1
69*e1fe3e4aSElliott Hughes        if not ((i + 1) % 8):
70*e1fe3e4aSElliott Hughes            items.append(binary)
71*e1fe3e4aSElliott Hughes            binary = ""
72*e1fe3e4aSElliott Hughes    if binary:
73*e1fe3e4aSElliott Hughes        items.append(binary)
74*e1fe3e4aSElliott Hughes    items.reverse()
75*e1fe3e4aSElliott Hughes    assert l in (0, -1), "number doesn't fit in number of bits"
76*e1fe3e4aSElliott Hughes    return " ".join(items)
77*e1fe3e4aSElliott Hughes
78*e1fe3e4aSElliott Hughes
79*e1fe3e4aSElliott Hughesdef binary2num(bin):
80*e1fe3e4aSElliott Hughes    bin = strjoin(bin.split())
81*e1fe3e4aSElliott Hughes    l = 0
82*e1fe3e4aSElliott Hughes    for digit in bin:
83*e1fe3e4aSElliott Hughes        l = l << 1
84*e1fe3e4aSElliott Hughes        if digit != "0":
85*e1fe3e4aSElliott Hughes            l = l | 0x1
86*e1fe3e4aSElliott Hughes    return l
87*e1fe3e4aSElliott Hughes
88*e1fe3e4aSElliott Hughes
89*e1fe3e4aSElliott Hughesdef caselessSort(alist):
90*e1fe3e4aSElliott Hughes    """Return a sorted copy of a list. If there are only strings
91*e1fe3e4aSElliott Hughes    in the list, it will not consider case.
92*e1fe3e4aSElliott Hughes    """
93*e1fe3e4aSElliott Hughes
94*e1fe3e4aSElliott Hughes    try:
95*e1fe3e4aSElliott Hughes        return sorted(alist, key=lambda a: (a.lower(), a))
96*e1fe3e4aSElliott Hughes    except TypeError:
97*e1fe3e4aSElliott Hughes        return sorted(alist)
98*e1fe3e4aSElliott Hughes
99*e1fe3e4aSElliott Hughes
100*e1fe3e4aSElliott Hughesdef pad(data, size):
101*e1fe3e4aSElliott Hughes    r"""Pad byte string 'data' with null bytes until its length is a
102*e1fe3e4aSElliott Hughes    multiple of 'size'.
103*e1fe3e4aSElliott Hughes
104*e1fe3e4aSElliott Hughes    >>> len(pad(b'abcd', 4))
105*e1fe3e4aSElliott Hughes    4
106*e1fe3e4aSElliott Hughes    >>> len(pad(b'abcde', 2))
107*e1fe3e4aSElliott Hughes    6
108*e1fe3e4aSElliott Hughes    >>> len(pad(b'abcde', 4))
109*e1fe3e4aSElliott Hughes    8
110*e1fe3e4aSElliott Hughes    >>> pad(b'abcdef', 4) == b'abcdef\x00\x00'
111*e1fe3e4aSElliott Hughes    True
112*e1fe3e4aSElliott Hughes    """
113*e1fe3e4aSElliott Hughes    data = tobytes(data)
114*e1fe3e4aSElliott Hughes    if size > 1:
115*e1fe3e4aSElliott Hughes        remainder = len(data) % size
116*e1fe3e4aSElliott Hughes        if remainder:
117*e1fe3e4aSElliott Hughes            data += b"\0" * (size - remainder)
118*e1fe3e4aSElliott Hughes    return data
119*e1fe3e4aSElliott Hughes
120*e1fe3e4aSElliott Hughes
121*e1fe3e4aSElliott Hughesdef tostr(s, encoding="ascii", errors="strict"):
122*e1fe3e4aSElliott Hughes    if not isinstance(s, str):
123*e1fe3e4aSElliott Hughes        return s.decode(encoding, errors)
124*e1fe3e4aSElliott Hughes    else:
125*e1fe3e4aSElliott Hughes        return s
126*e1fe3e4aSElliott Hughes
127*e1fe3e4aSElliott Hughes
128*e1fe3e4aSElliott Hughesdef tobytes(s, encoding="ascii", errors="strict"):
129*e1fe3e4aSElliott Hughes    if isinstance(s, str):
130*e1fe3e4aSElliott Hughes        return s.encode(encoding, errors)
131*e1fe3e4aSElliott Hughes    else:
132*e1fe3e4aSElliott Hughes        return bytes(s)
133*e1fe3e4aSElliott Hughes
134*e1fe3e4aSElliott Hughes
135*e1fe3e4aSElliott Hughesdef bytechr(n):
136*e1fe3e4aSElliott Hughes    return bytes([n])
137*e1fe3e4aSElliott Hughes
138*e1fe3e4aSElliott Hughes
139*e1fe3e4aSElliott Hughesdef byteord(c):
140*e1fe3e4aSElliott Hughes    return c if isinstance(c, int) else ord(c)
141*e1fe3e4aSElliott Hughes
142*e1fe3e4aSElliott Hughes
143*e1fe3e4aSElliott Hughesdef strjoin(iterable, joiner=""):
144*e1fe3e4aSElliott Hughes    return tostr(joiner).join(iterable)
145*e1fe3e4aSElliott Hughes
146*e1fe3e4aSElliott Hughes
147*e1fe3e4aSElliott Hughesdef bytesjoin(iterable, joiner=b""):
148*e1fe3e4aSElliott Hughes    return tobytes(joiner).join(tobytes(item) for item in iterable)
149*e1fe3e4aSElliott Hughes
150*e1fe3e4aSElliott Hughes
151*e1fe3e4aSElliott Hughesif __name__ == "__main__":
152*e1fe3e4aSElliott Hughes    import doctest, sys
153*e1fe3e4aSElliott Hughes
154*e1fe3e4aSElliott Hughes    sys.exit(doctest.testmod().failed)
155