1999-12-16 21:34:53 +00:00
|
|
|
"""fontTools.misc.textTools.py -- miscelaneous routines."""
|
|
|
|
|
|
|
|
|
2013-11-27 17:46:17 -05:00
|
|
|
from __future__ import print_function, division
|
2013-11-27 17:27:45 -05:00
|
|
|
from fontTools.misc.py23 import *
|
1999-12-16 21:34:53 +00:00
|
|
|
import string
|
|
|
|
|
|
|
|
|
2013-11-25 03:52:30 -05:00
|
|
|
def safeEval(data, eval=eval):
|
2012-10-18 12:49:22 +00:00
|
|
|
"""A (kindof) safe replacement for eval."""
|
2013-11-25 03:52:30 -05:00
|
|
|
return eval(data, {"__builtins__":{}})
|
1999-12-16 21:34:53 +00:00
|
|
|
|
|
|
|
|
|
|
|
def readHex(content):
|
|
|
|
"""Convert a list of hex strings to binary data."""
|
2013-11-27 23:37:57 -05:00
|
|
|
return deHexStr(strjoin(chunk for chunk in content if isinstance(chunk, basestring)))
|
1999-12-16 21:34:53 +00:00
|
|
|
|
|
|
|
def deHexStr(hexdata):
|
|
|
|
"""Convert a hex string to binary data."""
|
2013-11-27 21:17:35 -05:00
|
|
|
hexdata = strjoin(hexdata.split())
|
1999-12-16 21:34:53 +00:00
|
|
|
if len(hexdata) % 2:
|
|
|
|
hexdata = hexdata + "0"
|
2007-08-25 06:19:37 +00:00
|
|
|
data = []
|
1999-12-16 21:34:53 +00:00
|
|
|
for i in range(0, len(hexdata), 2):
|
2013-11-27 15:19:40 -05:00
|
|
|
data.append(bytechr(int(hexdata[i:i+2], 16)))
|
2013-11-27 21:17:35 -05:00
|
|
|
return bytesjoin(data)
|
2007-08-25 06:19:37 +00:00
|
|
|
|
1999-12-16 21:34:53 +00:00
|
|
|
|
|
|
|
def hexStr(data):
|
|
|
|
"""Convert binary data to a hex string."""
|
|
|
|
h = string.hexdigits
|
|
|
|
r = ''
|
|
|
|
for c in data:
|
2013-11-27 18:13:48 -05:00
|
|
|
i = byteord(c)
|
1999-12-16 21:34:53 +00:00
|
|
|
r = r + h[(i >> 4) & 0xF] + h[i & 0xF]
|
|
|
|
return r
|
|
|
|
|
|
|
|
|
|
|
|
def num2binary(l, bits=32):
|
|
|
|
all = []
|
|
|
|
bin = ""
|
|
|
|
for i in range(bits):
|
|
|
|
if l & 0x1:
|
|
|
|
bin = "1" + bin
|
|
|
|
else:
|
|
|
|
bin = "0" + bin
|
|
|
|
l = l >> 1
|
|
|
|
if not ((i+1) % 8):
|
|
|
|
all.append(bin)
|
|
|
|
bin = ""
|
2000-02-01 15:28:18 +00:00
|
|
|
if bin:
|
|
|
|
all.append(bin)
|
1999-12-16 21:34:53 +00:00
|
|
|
all.reverse()
|
|
|
|
assert l in (0, -1), "number doesn't fit in number of bits"
|
2013-11-27 05:47:34 -05:00
|
|
|
return ' '.join(all)
|
1999-12-16 21:34:53 +00:00
|
|
|
|
|
|
|
|
|
|
|
def binary2num(bin):
|
2013-11-27 21:17:35 -05:00
|
|
|
bin = strjoin(bin.split())
|
1999-12-16 21:34:53 +00:00
|
|
|
l = 0
|
|
|
|
for digit in bin:
|
|
|
|
l = l << 1
|
2013-11-27 02:40:30 -05:00
|
|
|
if digit != "0":
|
1999-12-16 21:34:53 +00:00
|
|
|
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:
|
|
|
|
# turn ['FOO', 'aaBc', 'ABcD'] into
|
|
|
|
# [('foo', 'FOO'), ('aabc', 'aaBc'), ('abcd', 'ABcD')],
|
|
|
|
# but only if all elements are strings
|
2013-11-27 04:38:16 -05:00
|
|
|
tupledlist = [(item.lower(), item) for item in alist]
|
1999-12-16 21:34:53 +00:00
|
|
|
except TypeError:
|
|
|
|
# at least one element in alist is not a string, proceed the normal way...
|
2013-11-27 04:15:34 -05:00
|
|
|
alist = sorted(alist[:])
|
1999-12-16 21:34:53 +00:00
|
|
|
return alist
|
|
|
|
else:
|
|
|
|
tupledlist.sort()
|
|
|
|
# turn [('aabc', 'aaBc'), ('abcd', 'ABcD'), ('foo', 'FOO')] into
|
|
|
|
# ['aaBc', 'ABcD', 'FOO']
|
2013-11-27 04:38:16 -05:00
|
|
|
return [x[1] for x in tupledlist]
|
1999-12-16 21:34:53 +00:00
|
|
|
|