parse_link_destination.py 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. """
  2. Parse link destination
  3. """
  4. from ..common.utils import charCodeAt, unescapeAll
  5. class _Result:
  6. __slots__ = ("ok", "pos", "str")
  7. def __init__(self) -> None:
  8. self.ok = False
  9. self.pos = 0
  10. self.str = ""
  11. def parseLinkDestination(string: str, pos: int, maximum: int) -> _Result:
  12. start = pos
  13. result = _Result()
  14. if charCodeAt(string, pos) == 0x3C: # /* < */
  15. pos += 1
  16. while pos < maximum:
  17. code = charCodeAt(string, pos)
  18. if code == 0x0A: # /* \n */)
  19. return result
  20. if code == 0x3C: # / * < * /
  21. return result
  22. if code == 0x3E: # /* > */) {
  23. result.pos = pos + 1
  24. result.str = unescapeAll(string[start + 1 : pos])
  25. result.ok = True
  26. return result
  27. if code == 0x5C and pos + 1 < maximum: # \
  28. pos += 2
  29. continue
  30. pos += 1
  31. # no closing '>'
  32. return result
  33. # this should be ... } else { ... branch
  34. level = 0
  35. while pos < maximum:
  36. code = charCodeAt(string, pos)
  37. if code is None or code == 0x20:
  38. break
  39. # ascii control characters
  40. if code < 0x20 or code == 0x7F:
  41. break
  42. if code == 0x5C and pos + 1 < maximum:
  43. if charCodeAt(string, pos + 1) == 0x20:
  44. break
  45. pos += 2
  46. continue
  47. if code == 0x28: # /* ( */)
  48. level += 1
  49. if level > 32:
  50. return result
  51. if code == 0x29: # /* ) */)
  52. if level == 0:
  53. break
  54. level -= 1
  55. pos += 1
  56. if start == pos:
  57. return result
  58. if level != 0:
  59. return result
  60. result.str = unescapeAll(string[start:pos])
  61. result.pos = pos
  62. result.ok = True
  63. return result