textTools.py 3.3 KB

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