1cimport cython
2
3cdef extern from *:
4    cdef Py_ssize_t PY_SSIZE_T_MIN
5    cdef Py_ssize_t PY_SSIZE_T_MAX
6
7SSIZE_T_MAX = PY_SSIZE_T_MAX
8SSIZE_T_MIN = PY_SSIZE_T_MIN
9
10
11b_a = b'a'
12b_b = b'b'
13
14
15@cython.test_assert_path_exists(
16    "//PythonCapiCallNode")
17@cython.test_fail_if_path_exists(
18    "//SimpleCallNode")
19def bytes_startswith(bytes s, sub, start=None, stop=None):
20    """
21    >>> bytes_startswith(b_a, b_a)
22    True
23    >>> bytes_startswith(b_a+b_b, b_a)
24    True
25    >>> bytes_startswith(b_a, b_b)
26    False
27    >>> bytes_startswith(b_a+b_b, b_b)
28    False
29    >>> bytes_startswith(b_a, (b_a, b_b))
30    True
31    >>> bytes_startswith(b_a, b_a, 1)
32    False
33    >>> bytes_startswith(b_a, b_a, 0, 0)
34    False
35    """
36
37    if start is None:
38      return s.startswith(sub)
39    elif stop is None:
40      return s.startswith(sub, start)
41    else:
42      return s.startswith(sub, start, stop)
43
44
45@cython.test_assert_path_exists(
46    "//PythonCapiCallNode")
47@cython.test_fail_if_path_exists(
48    "//SimpleCallNode")
49def bytes_endswith(bytes s, sub, start=None, stop=None):
50    """
51    >>> bytes_endswith(b_a, b_a)
52    True
53    >>> bytes_endswith(b_b+b_a, b_a)
54    True
55    >>> bytes_endswith(b_a, b_b)
56    False
57    >>> bytes_endswith(b_b+b_a, b_b)
58    False
59    >>> bytes_endswith(b_a, (b_a, b_b))
60    True
61    >>> bytes_endswith(b_a, b_a, 1)
62    False
63    >>> bytes_endswith(b_a, b_a, 0, 0)
64    False
65    """
66
67    if start is None:
68      return s.endswith(sub)
69    elif stop is None:
70      return s.endswith(sub, start)
71    else:
72      return s.endswith(sub, start, stop)
73
74
75@cython.test_assert_path_exists(
76    "//PythonCapiCallNode")
77@cython.test_fail_if_path_exists(
78    "//SimpleCallNode")
79def bytes_decode(bytes s, start=None, stop=None):
80    """
81    >>> s = b_a+b_b+b_a+b_a+b_b
82    >>> print(bytes_decode(s))
83    abaab
84
85    >>> print(bytes_decode(s, 2))
86    aab
87    >>> print(bytes_decode(s, -3))
88    aab
89
90    >>> print(bytes_decode(s, None, 4))
91    abaa
92    >>> print(bytes_decode(s, None, 400))
93    abaab
94    >>> print(bytes_decode(s, None, -2))
95    aba
96    >>> print(bytes_decode(s, None, -4))
97    a
98    >>> print(bytes_decode(s, None, -5))
99    <BLANKLINE>
100    >>> print(bytes_decode(s, None, -200))
101    <BLANKLINE>
102
103    >>> print(bytes_decode(s, 2, 5))
104    aab
105    >>> print(bytes_decode(s, 2, 500))
106    aab
107    >>> print(bytes_decode(s, 2, -1))
108    aa
109    >>> print(bytes_decode(s, 2, -3))
110    <BLANKLINE>
111    >>> print(bytes_decode(s, 2, -300))
112    <BLANKLINE>
113    >>> print(bytes_decode(s, -3, -1))
114    aa
115    >>> print(bytes_decode(s, -300, 300))
116    abaab
117    >>> print(bytes_decode(s, -300, -4))
118    a
119    >>> print(bytes_decode(s, -300, -5))
120    <BLANKLINE>
121    >>> print(bytes_decode(s, -300, -6))
122    <BLANKLINE>
123    >>> print(bytes_decode(s, -300, -500))
124    <BLANKLINE>
125    >>> print(bytes_decode(s, SSIZE_T_MIN, SSIZE_T_MIN))
126    <BLANKLINE>
127    >>> print(bytes_decode(s, SSIZE_T_MIN, SSIZE_T_MAX))
128    abaab
129    >>> print(bytes_decode(s, SSIZE_T_MAX, SSIZE_T_MIN))
130    <BLANKLINE>
131    >>> print(bytes_decode(s, SSIZE_T_MAX, SSIZE_T_MAX))
132    <BLANKLINE>
133
134    >>> s[:'test']                       # doctest: +ELLIPSIS
135    Traceback (most recent call last):
136    TypeError:...
137    >>> print(bytes_decode(s, 'test'))   # doctest: +ELLIPSIS
138    Traceback (most recent call last):
139    TypeError:...
140    >>> print(bytes_decode(s, None, 'test'))    # doctest: +ELLIPSIS
141    Traceback (most recent call last):
142    TypeError:...
143    >>> print(bytes_decode(s, 'test', 'test'))  # doctest: +ELLIPSIS
144    Traceback (most recent call last):
145    TypeError:...
146
147    >>> print(bytes_decode(None))
148    Traceback (most recent call last):
149    AttributeError: 'NoneType' object has no attribute 'decode'
150    >>> print(bytes_decode(None, 1))
151    Traceback (most recent call last):
152    TypeError: 'NoneType' object is not subscriptable
153    >>> print(bytes_decode(None, None, 1))
154    Traceback (most recent call last):
155    TypeError: 'NoneType' object is not subscriptable
156    >>> print(bytes_decode(None, 0, 1))
157    Traceback (most recent call last):
158    TypeError: 'NoneType' object is not subscriptable
159    """
160    if start is None:
161        if stop is None:
162            return s.decode('utf8')
163        else:
164            return s[:stop].decode('utf8')
165    elif stop is None:
166        return s[start:].decode('utf8')
167    else:
168        return s[start:stop].decode('utf8')
169
170
171@cython.test_assert_path_exists(
172    "//PythonCapiCallNode")
173@cython.test_fail_if_path_exists(
174    "//SimpleCallNode")
175def bytes_decode_utf16(bytes s):
176    """
177    >>> s = 'abc'.encode('UTF-16')
178    >>> print(bytes_decode_utf16(s))
179    abc
180    """
181    return s.decode('utf16')
182
183
184@cython.test_assert_path_exists(
185    "//PythonCapiCallNode")
186@cython.test_fail_if_path_exists(
187    "//SimpleCallNode")
188def bytes_decode_utf16_le(bytes s):
189    """
190    >>> s = 'abc'.encode('UTF-16LE')
191    >>> assert s != 'abc'.encode('UTF-16BE')
192    >>> print(bytes_decode_utf16_le(s))
193    abc
194    """
195    return s.decode('utf_16_le')
196
197
198@cython.test_assert_path_exists(
199    "//PythonCapiCallNode")
200@cython.test_fail_if_path_exists(
201    "//SimpleCallNode")
202def bytes_decode_utf16_be(bytes s):
203    """
204    >>> s = 'abc'.encode('UTF-16BE')
205    >>> assert s != 'abc'.encode('UTF-16LE')
206    >>> print(bytes_decode_utf16_be(s))
207    abc
208    """
209    return s.decode('utf_16_be')
210
211
212@cython.test_assert_path_exists(
213    "//PythonCapiCallNode")
214@cython.test_fail_if_path_exists(
215    "//SimpleCallNode")
216def bytes_decode_unbound_method(bytes s, start=None, stop=None):
217    """
218    >>> s = b_a+b_b+b_a+b_a+b_b
219    >>> print(bytes_decode_unbound_method(s))
220    abaab
221    >>> print(bytes_decode_unbound_method(s, 1))
222    baab
223    >>> print(bytes_decode_unbound_method(s, None, 3))
224    aba
225    >>> print(bytes_decode_unbound_method(s, 1, 4))
226    baa
227
228    >>> print(bytes_decode_unbound_method(None))
229    Traceback (most recent call last):
230    TypeError: descriptor 'decode' requires a 'bytes' object but received a 'NoneType'
231    >>> print(bytes_decode_unbound_method(None, 1))
232    Traceback (most recent call last):
233    TypeError: 'NoneType' object is not subscriptable
234    >>> print(bytes_decode_unbound_method(None, None, 1))
235    Traceback (most recent call last):
236    TypeError: 'NoneType' object is not subscriptable
237    >>> print(bytes_decode_unbound_method(None, 0, 1))
238    Traceback (most recent call last):
239    TypeError: 'NoneType' object is not subscriptable
240    """
241    if start is None:
242        if stop is None:
243            return bytes.decode(s, 'utf8')
244        else:
245            return bytes.decode(s[:stop], 'utf8')
246    elif stop is None:
247        return bytes.decode(s[start:], 'utf8')
248    else:
249        return bytes.decode(s[start:stop], 'utf8')
250
251
252@cython.test_assert_path_exists(
253    "//SimpleCallNode",
254    "//SimpleCallNode//NoneCheckNode",
255    "//SimpleCallNode//AttributeNode[@is_py_attr = false]")
256def bytes_join(bytes s, *args):
257    """
258    >>> print(bytes_join(b_a, b_b, b_b, b_b).decode('utf8'))
259    babab
260    """
261    result = s.join(args)
262    assert cython.typeof(result) == 'Python object', cython.typeof(result)
263    return result
264
265
266@cython.test_fail_if_path_exists(
267    "//SimpleCallNode//NoneCheckNode",
268)
269@cython.test_assert_path_exists(
270    "//SimpleCallNode",
271    "//SimpleCallNode//AttributeNode[@is_py_attr = false]")
272def literal_join(*args):
273    """
274    >>> print(literal_join(b_b, b_b, b_b, b_b).decode('utf8'))
275    b|b|b|b
276    """
277    result = b'|'.join(args)
278    assert cython.typeof(result) == 'Python object', cython.typeof(result)
279    return result
280