annotate runes.py @ 23:dc30266d4d5b

Add --backtick mode.
author David Barts <n5jrn@me.com>
date Wed, 15 Jan 2020 09:06:55 -0800
parents a771878f6cf4
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
10
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
1 #!/usr/bin/env python3
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
2 # -*- coding: utf-8 -*-
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
3
22
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
4 # Something like Java's StringBuilder, but for Python. It needs more
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
5 # thorough testing. This runs about 3x slower than io.StringIO, but
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
6 # unlike that class allows for easy and meaningful random access via
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
7 # subscripts.
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
8 #
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
9 # This implements two objects: Runes and Workspace. The former is a
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
10 # relatively low-level object that deals mostly in UTF-16 rune values;
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
11 # however, you can create a Runes object from a Python string, and you
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
12 # can create a Python string from a Runes object. Aside from that, Runes
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
13 # deals in numeric values, not Python strings. Workspace methods tend
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
14 # to accept and return Python strings, which makes them more programmer-
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
15 # friendly, at the cost of often having to fire up a codec to convert
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
16 # things back and forth between Python strings and UTF-16 runes.
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
17
10
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
18 # I m p o r t s
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
19
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
20 import array
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
21 import codecs
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
22 import sys
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
23
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
24 # C l a s s e s
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
25
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
26 class Runes(object):
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
27 """
22
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
28 A mutable sequence of UTF-16 runes. The attributes encoding and
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
29 codec contain the name of the encoding and the codec used to
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
30 generate the UTF-16. The attribute buffer contains the buffer (an
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
31 array of 16-bit unsigned integers) used to back this object;
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
32 modifications to that array will be reflected in this object.
10
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
33 """
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
34 # The most efficient 16-bit one on this platform
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
35 encoding = "UTF-16" + sys.byteorder[0].upper() + "E"
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
36 codec = codecs.lookup(encoding)
22
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
37 _ERRORS = 'surrogatepass'
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
38 _MIN_S = 0xd800 # lowest possible surrogate
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
39 _MID_S = 0xdc00 # high surrogate if <, low if >=
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
40 _MAX_S = 0xdfff # highest possible surrogate
10
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
41
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
42 def __init__(self, based_on=None):
20
be0fd5c8121d Can't use memoryview to base Runes on; different methods inside.
David Barts <n5jrn@me.com>
parents: 17
diff changeset
43 if isinstance(based_on, array.array):
be0fd5c8121d Can't use memoryview to base Runes on; different methods inside.
David Barts <n5jrn@me.com>
parents: 17
diff changeset
44 if based_on.typecode == 'H':
10
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
45 self.buffer = based_on
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
46 else:
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
47 self.buffer = array.array('H', based_on)
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
48 elif isinstance(based_on, str):
22
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
49 self.buffer = array.array('H', self.codec.encode(based_on, self._ERRORS)[0])
10
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
50 elif based_on is None:
22
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
51 self.buffer = array.array('H')
12
ab7d6e908034 Allow cloning.
David Barts <n5jrn@me.com>
parents: 10
diff changeset
52 elif isinstance(based_on, Runes):
ab7d6e908034 Allow cloning.
David Barts <n5jrn@me.com>
parents: 10
diff changeset
53 self.buffer = array.array('H', based_on.buffer)
10
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
54 else:
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
55 self.buffer = array.array('H', based_on)
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
56
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
57 def __str__(self):
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
58 """
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
59 Convert this object to a string. We deliberately do not have a
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
60 __repr__ method, to underscore that runes are not strings.
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
61 """
22
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
62 return self.codec.decode(self.buffer, self._ERRORS)[0]
10
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
63
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
64 def __bytes__(self):
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
65 return bytes(self.buffer)
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
66
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
67 def __len__(self):
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
68 return len(self.buffer)
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
69
22
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
70 def _checkindex(self, index, allow_equal=False):
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
71 ok = 0 <= index <= len(self) if allow_equal else 0 <= index < len(self)
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
72 if not ok:
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
73 raise IndexError("index {0} out of range".format(index))
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
74
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
75 def _checktype(self, other):
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
76 if not isinstance(other, Runes):
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
77 raise TypeError("Runes required")
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
78
10
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
79 def __lt__(self, other):
22
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
80 self._checktype(other)
10
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
81 return self.buffer < other.buffer
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
82
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
83 def __le__(self, other):
22
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
84 self._checktype(other)
10
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
85 return self.buffer <= other.buffer
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
86
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
87 def __gt__(self, other):
22
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
88 self._checktype(other)
10
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
89 return self.buffer > other.buffer
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
90
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
91 def __ge__(self, other):
22
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
92 self._checktype(other)
10
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
93 return self.buffer >= other.buffer
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
94
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
95 def __eq__(self, other):
22
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
96 self._checktype(other)
10
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
97 return self.buffer == other.buffer
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
98
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
99 def __ne__(self, other):
22
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
100 self._checktype(other)
10
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
101 return self.buffer != other.buffer
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
102
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
103 def __hash__(self):
13
6acda841a690 Add support for shared substrings.
David Barts <n5jrn@me.com>
parents: 12
diff changeset
104 raise TypeError("unhashable type")
10
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
105
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
106 def __bool__(self):
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
107 return bool(self.buffer)
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
108
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
109 def __getitem__(self, key):
22
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
110 if isinstance(key, int):
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
111 return self.buffer[key]
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
112 elif isinstance(key, slice):
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
113 return Runes(self.buffer[key])
10
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
114 else:
22
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
115 raise AssertionError("this shouldn't happen")
10
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
116
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
117 def __setitem__(self, key, value):
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
118 if isinstance(key, int):
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
119 if isinstance(value, int):
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
120 self.buffer[key] = value
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
121 else:
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
122 raise TypeError("integer required")
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
123 elif isinstance(value, Runes):
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
124 self.buffer[key] = value.buffer
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
125 else:
22
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
126 raise TypeError("Runes required")
10
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
127
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
128 def __delitem__(self, key):
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
129 del self.buffer[key]
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
130
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
131 def clear(self):
22
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
132 """
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
133 Remove all data from our buffer. This merely marks the buffer as
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
134 empty; it does nothing to destroy its contents by overwriting.
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
135 """
10
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
136 del self[:]
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
137
22
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
138 def zero(self):
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
139 """
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
140 Overwrite our buffer with zeroes.
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
141 """
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
142 for i in range(len(self.buffer)):
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
143 self.buffer[i] = 0
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
144
10
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
145 def __iter__(self):
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
146 return iter(self.buffer)
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
147
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
148 def __reversed__(self):
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
149 return reversed(self.buffer)
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
150
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
151 def append(self, value):
22
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
152 """
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
153 Append data to our buffer.
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
154 """
10
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
155 if isinstance(value, int):
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
156 self.buffer.append(value)
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
157 elif isinstance(value, Runes):
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
158 self.buffer.extend(value.buffer)
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
159 else:
22
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
160 raise TypeError("integer or Runes required")
10
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
161
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
162 def __contains__(self, value):
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
163 return value in self.buffer
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
164
22
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
165 @classmethod
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
166 def is_high_surrogate(cls, value):
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
167 """
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
168 Is value in the UTF-16 high surrogate range?
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
169 """
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
170 return cls._MIN_S <= value < cls._MID_S
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
171
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
172 @classmethod
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
173 def is_low_surrogate(cls, value):
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
174 """
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
175 Is value in the UTF-16 low surrogate range?
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
176 """
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
177 return cls._MIN_S <= value <= cls._MAX_S
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
178
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
179 @classmethod
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
180 def is_surrogate(cls, value):
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
181 """
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
182 Is value in the UTF-16 surrogate range?
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
183 """
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
184 return cls._MIN_S <= value <= cls._MAX_S
10
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
185
22
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
186 def index(self, value, from_index=0):
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
187 """
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
188 Substring index, throws exception if not found.
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
189 """
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
190 self._checktype(value)
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
191 slimit = len(self)
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
192 rlimit = len(value)
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
193 for i in range(from_index, len(self)):
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
194 match = True
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
195 for j in range(rlimit):
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
196 k = i + j
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
197 if k >= slimit or value.buffer[j] != self.buffer[k]:
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
198 match = False
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
199 break
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
200 if match:
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
201 return i
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
202 raise ValueError("substring not found")
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
203
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
204 def find(self, value, from_index=0):
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
205 """
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
206 Substring index, returns -1 if not found.
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
207 """
10
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
208 try:
22
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
209 return self.index(value, from_index)
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
210 except ValueError:
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
211 return -1
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
212
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
213 def rindex(self, value, from_index=None):
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
214 """
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
215 Reverse substring index, throws exception if not found.
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
216 """
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
217 self._checktype(value)
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
218 if from_index is None:
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
219 from_index = len(self) - 1
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
220 rfrom = len(value) - 1
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
221 for i in range(from_index, -1, -1):
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
222 match = True
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
223 for j in range(rfrom, -1, -1):
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
224 k = i - (rfrom - j)
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
225 if k < 0 or value.buffer[j] != self.buffer[k]:
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
226 match = False
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
227 break
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
228 if match:
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
229 return i - rfrom
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
230 raise ValueError("substring not found")
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
231
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
232 def rfind(self, value, from_index=None):
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
233 """
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
234 Reverse substring index, returns -1 if not found.
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
235 """
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
236 try:
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
237 return self.rindex(value, from_index)
10
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
238 except ValueError:
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
239 return -1
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
240
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
241 class Workspace(Runes):
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
242 """
22
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
243 A Runes object (q.v.) that acts a bit more string-like.
10
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
244 """
22
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
245
10
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
246 def __setitem__(self, key, value):
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
247 if isinstance(value, str):
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
248 if isinstance(key, int):
22
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
249 value = ord(value)
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
250 if value > 0xffff:
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
251 raise ValueError("character not in BMP")
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
252 super().__setitem__(key, value)
10
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
253 else:
22
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
254 super().__setitem__(key, Runes(value))
10
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
255 else:
22
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
256 super().__setitem__(key, value)
10
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
257
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
258 def __getitem__(self, key):
22
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
259 if isinstance(key, int):
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
260 return chr(self.buffer[key])
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
261 elif isinstance(key, slice):
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
262 view = memoryview(self.buffer)
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
263 try:
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
264 result = view[key]
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
265 if not isinstance(result, memoryview):
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
266 assert isinstance(result, int)
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
267 return chr(result)
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
268 ret = self.codec.decode(result, self._ERRORS)[0]
15
0be0586104b7 Plug the leak properly (I hope).
David Barts <n5jrn@me.com>
parents: 14
diff changeset
269 result.release()
0be0586104b7 Plug the leak properly (I hope).
David Barts <n5jrn@me.com>
parents: 14
diff changeset
270 return ret
22
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
271 finally:
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
272 view.release()
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
273 else:
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
274 raise AssertionError("this shouldn't happen")
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
275
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
276 def __contains__(self, value):
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
277 if isinstance(value, int):
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
278 return value in self.buffer
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
279 return self.find(value) != -1
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
280
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
281 def __iter__(self):
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
282 for i in range(len(self)):
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
283 yield self[i]
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
284
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
285 def __reversed__(self):
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
286 for i in range(len(self)-1, -1, -1):
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
287 yield self[i]
10
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
288
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
289 def append(self, value):
22
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
290 """
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
291 Append string or runes to this item.
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
292 """
10
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
293 if isinstance(value, str):
22
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
294 value = Runes(value)
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
295 elif not isinstance(value, (int, Runes)):
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
296 raise TypeError("integer, string, or Runes required")
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
297 super().append(value)
10
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
298
22
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
299 def _runify(self, value):
10
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
300 if isinstance(value, str):
22
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
301 return Runes(value)
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
302 elif isinstance(value, Runes):
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
303 return value
10
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
304 else:
22
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
305 raise TypeError("Runes or string required")
10
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
306
22
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
307 def index(self, value, from_index=0):
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
308 """
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
309 Substring index, throws exception if not found.
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
310 """
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
311 return super().index(self._runify(value), from_index)
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
312
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
313 def find(self, value, from_index=0):
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
314 """
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
315 Substring index, returns -1 if not found.
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
316 """
10
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
317 try:
22
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
318 return self.index(value, from_index)
10
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
319 except ValueError:
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
320 return -1
397c178c5b98 Make it array-based.
David Barts <n5jrn@me.com>
parents:
diff changeset
321
22
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
322 def rindex(self, value, from_index=None):
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
323 """
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
324 Reverse substring index, throws exception if not found.
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
325 """
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
326 return super().rindex(self._runify(value), from_index)
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
327
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
328 def rfind(self, value, from_index=None):
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
329 """
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
330 Reverse substring index, returns -1 if not found.
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
331 """
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
332 try:
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
333 return self.rindex(value, from_index)
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
334 except ValueError:
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
335 return -1
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
336
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
337 def _code_point_at(self, index):
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
338 self._checkindex(index, allow_equal=False)
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
339 v0 = self.buffer[index]
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
340 i1 = index + 1
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
341 v1 = None if i1 >= len(self.buffer) else self.buffer[i1]
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
342 if Runes.is_high_surrogate(v0) and v1 is not None and Runes.is_low_surrogate(v1):
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
343 return slice(index, index+2)
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
344 else:
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
345 return slice(index, i1)
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
346
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
347 def code_point_at(self, index):
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
348 """
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
349 Similar to java.lang.String.codePointAt, but returns a 1-character
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
350 string, not an int.
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
351 """
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
352 return self[self._code_point_at(index)]
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
353
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
354 def _code_point_before(self, index):
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
355 self._checkindex(index - 1, allow_equal=True)
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
356 i1 = index - 1
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
357 v1 = self.buffer[i1]
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
358 i2 = index - 2
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
359 v2 = None if i2 < 0 else self.buffer[i2]
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
360 if Runes.is_low_surrogate(v1) and v2 is not None and Runes.is_high_surrogate(v2):
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
361 return slice(i2, index)
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
362 else:
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
363 return slice(i1, index)
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
364
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
365 def code_point_before(self, index):
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
366 """
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
367 Similar to java.lang.String.codePointBefore but returns a 1-character
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
368 string, not an int.
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
369 """
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
370 return self[self._code_point_before(index)]
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
371
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
372 def code_point_count(self, begin=None, end=None):
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
373 """
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
374 Same behavior as java.lang.String.codePointCount (q.v.).
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
375 """
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
376 if begin is None: begin = 0
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
377 if end is None: end = len(self.buffer)
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
378 self._checkindex(begin, allow_equal=False)
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
379 self._checkindex(end, allow_equal=True)
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
380 if begin > end:
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
381 raise IndexError("invalid range (begin > end)")
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
382 i = begin
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
383 ret = 0
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
384 while i < end:
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
385 i = self._code_point_at(i).stop
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
386 ret += 1
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
387 return ret
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
388
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
389 def offset_by_code_points(self, index, offset):
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
390 """
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
391 Same behavior as java.lang.String.offsetByCodePoints (q.v.).
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
392 """
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
393 self._checkindex(index, allow_equal=True)
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
394 if offset < 0:
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
395 next = lambda i: self._code_point_before(i).start
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
396 else:
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
397 next = lambda i: self._code_point_at(i).stop
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
398 seen = 0
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
399 limit = abs(offset)
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
400 while seen < limit:
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
401 index = next(index)
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
402 seen += 1
a771878f6cf4 Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents: 21
diff changeset
403 return index