4 escape_code_point: int,
5 escaped_code_points: list[int],
6 escaped_by_code_points: list[int],
9 self.__escaped_code_points: list[int] = escaped_code_points
10 self.__escaped_by_code_points: list[int] = escaped_by_code_points
23 def escape(self, input_string: str) -> str:
28 result: list[str] = []
29 result.append(input_string[:no_escapes])
30 for char
in input_string[no_escapes:]:
31 codepoint: int = ord(char)
32 if codepoint
in self.__escaped_code_points:
33 idx: int = self.__escaped_code_points.index(codepoint)
35 result.append(chr(self.__escaped_by_code_points[idx]))
38 return "".join(result)
41 if input_string.endswith(
45 f
"Escape character '{chr(self.__escape_code_point)}' can't be the last character in a string."
52 result: list[str] = [input_string[:no_escapes]]
53 skip_next: bool =
False
54 for i
in range(no_escapes, len(input_string)):
58 codepoint: int = ord(input_string[i])
62 next_codepoint: int = ord(input_string[i + 1])
63 if next_codepoint
in self.__escaped_by_code_points:
64 idx: int = self.__escaped_by_code_points.index(next_codepoint)
65 result.append(chr(self.__escaped_code_points[idx]))
68 result.append(input_string[i + 1])
71 result.append(chr(codepoint))
72 return "".join(result)
75 def self_escape(cls, escape_policy: str) ->
"PerCharacterEscaper":
76 code_points: list[int] = [ord(c)
for c
in escape_policy]
77 escape_code_point: int = code_points[0]
78 return cls(escape_code_point, code_points, code_points)
82 code_points: list[int] = [ord(c)
for c
in escape_policy]
83 if len(code_points) % 2 != 0:
85 "Escape policy string must have an even number of characters."
87 escape_code_point: int = code_points[0]
88 escaped_code_points: list[int] = code_points[0::2]
89 escaped_by_code_points: list[int] = code_points[1::2]
90 return cls(escape_code_point, escaped_code_points, escaped_by_code_points)