766 lines
27 KiB
Python
766 lines
27 KiB
Python
|
"""
|
||
|
This module contains support functions for more advanced unicode operations.
|
||
|
This is not a public API and is for Numba internal use only. Most of the
|
||
|
functions are relatively straightforward translations of the functions with the
|
||
|
same name in CPython.
|
||
|
"""
|
||
|
from collections import namedtuple
|
||
|
from enum import IntEnum
|
||
|
|
||
|
import llvmlite.ir
|
||
|
import numpy as np
|
||
|
|
||
|
from numba.core import types, cgutils
|
||
|
from numba.core.imputils import (impl_ret_untracked)
|
||
|
|
||
|
from numba.core.extending import overload, intrinsic, register_jitable
|
||
|
from numba.core.errors import TypingError
|
||
|
|
||
|
# This is equivalent to the struct `_PyUnicode_TypeRecord defined in CPython's
|
||
|
# Objects/unicodectype.c
|
||
|
typerecord = namedtuple('typerecord',
|
||
|
'upper lower title decimal digit flags')
|
||
|
|
||
|
# The Py_UCS4 type from CPython:
|
||
|
# https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Include/unicodeobject.h#L112 # noqa: E501
|
||
|
_Py_UCS4 = types.uint32
|
||
|
|
||
|
# ------------------------------------------------------------------------------
|
||
|
# Start code related to/from CPython's unicodectype impl
|
||
|
#
|
||
|
# NOTE: the original source at:
|
||
|
# https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Objects/unicodectype.c # noqa: E501
|
||
|
# contains this statement:
|
||
|
#
|
||
|
# /*
|
||
|
# Unicode character type helpers.
|
||
|
#
|
||
|
# Written by Marc-Andre Lemburg (mal@lemburg.com).
|
||
|
# Modified for Python 2.0 by Fredrik Lundh (fredrik@pythonware.com)
|
||
|
#
|
||
|
# Copyright (c) Corporation for National Research Initiatives.
|
||
|
#
|
||
|
# */
|
||
|
|
||
|
|
||
|
# This enum contains the values defined in CPython's Objects/unicodectype.c that
|
||
|
# provide masks for use against the various members of the typerecord
|
||
|
#
|
||
|
# See: https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Objects/unicodectype.c#L13-L27 # noqa: E501
|
||
|
#
|
||
|
|
||
|
|
||
|
_Py_TAB = 0x9
|
||
|
_Py_LINEFEED = 0xa
|
||
|
_Py_CARRIAGE_RETURN = 0xd
|
||
|
_Py_SPACE = 0x20
|
||
|
|
||
|
|
||
|
class _PyUnicode_TyperecordMasks(IntEnum):
|
||
|
ALPHA_MASK = 0x01
|
||
|
DECIMAL_MASK = 0x02
|
||
|
DIGIT_MASK = 0x04
|
||
|
LOWER_MASK = 0x08
|
||
|
LINEBREAK_MASK = 0x10
|
||
|
SPACE_MASK = 0x20
|
||
|
TITLE_MASK = 0x40
|
||
|
UPPER_MASK = 0x80
|
||
|
XID_START_MASK = 0x100
|
||
|
XID_CONTINUE_MASK = 0x200
|
||
|
PRINTABLE_MASK = 0x400
|
||
|
NUMERIC_MASK = 0x800
|
||
|
CASE_IGNORABLE_MASK = 0x1000
|
||
|
CASED_MASK = 0x2000
|
||
|
EXTENDED_CASE_MASK = 0x4000
|
||
|
|
||
|
|
||
|
def _PyUnicode_gettyperecord(a):
|
||
|
raise RuntimeError("Calling the Python definition is invalid")
|
||
|
|
||
|
|
||
|
@intrinsic
|
||
|
def _gettyperecord_impl(typingctx, codepoint):
|
||
|
"""
|
||
|
Provides the binding to numba_gettyperecord, returns a `typerecord`
|
||
|
namedtuple of properties from the codepoint.
|
||
|
"""
|
||
|
if not isinstance(codepoint, types.Integer):
|
||
|
raise TypingError("codepoint must be an integer")
|
||
|
|
||
|
def details(context, builder, signature, args):
|
||
|
ll_void = context.get_value_type(types.void)
|
||
|
ll_Py_UCS4 = context.get_value_type(_Py_UCS4)
|
||
|
ll_intc = context.get_value_type(types.intc)
|
||
|
ll_intc_ptr = ll_intc.as_pointer()
|
||
|
ll_uchar = context.get_value_type(types.uchar)
|
||
|
ll_uchar_ptr = ll_uchar.as_pointer()
|
||
|
ll_ushort = context.get_value_type(types.ushort)
|
||
|
ll_ushort_ptr = ll_ushort.as_pointer()
|
||
|
fnty = llvmlite.ir.FunctionType(ll_void, [
|
||
|
ll_Py_UCS4, # code
|
||
|
ll_intc_ptr, # upper
|
||
|
ll_intc_ptr, # lower
|
||
|
ll_intc_ptr, # title
|
||
|
ll_uchar_ptr, # decimal
|
||
|
ll_uchar_ptr, # digit
|
||
|
ll_ushort_ptr, # flags
|
||
|
])
|
||
|
fn = cgutils.get_or_insert_function(
|
||
|
builder.module,
|
||
|
fnty, name="numba_gettyperecord")
|
||
|
upper = cgutils.alloca_once(builder, ll_intc, name='upper')
|
||
|
lower = cgutils.alloca_once(builder, ll_intc, name='lower')
|
||
|
title = cgutils.alloca_once(builder, ll_intc, name='title')
|
||
|
decimal = cgutils.alloca_once(builder, ll_uchar, name='decimal')
|
||
|
digit = cgutils.alloca_once(builder, ll_uchar, name='digit')
|
||
|
flags = cgutils.alloca_once(builder, ll_ushort, name='flags')
|
||
|
|
||
|
byref = [ upper, lower, title, decimal, digit, flags]
|
||
|
builder.call(fn, [args[0]] + byref)
|
||
|
buf = []
|
||
|
for x in byref:
|
||
|
buf.append(builder.load(x))
|
||
|
|
||
|
res = context.make_tuple(builder, signature.return_type, tuple(buf))
|
||
|
return impl_ret_untracked(context, builder, signature.return_type, res)
|
||
|
|
||
|
tupty = types.NamedTuple([types.intc, types.intc, types.intc, types.uchar,
|
||
|
types.uchar, types.ushort], typerecord)
|
||
|
sig = tupty(_Py_UCS4)
|
||
|
return sig, details
|
||
|
|
||
|
|
||
|
@overload(_PyUnicode_gettyperecord)
|
||
|
def gettyperecord_impl(a):
|
||
|
"""
|
||
|
Provides a _PyUnicode_gettyperecord binding, for convenience it will accept
|
||
|
single character strings and code points.
|
||
|
"""
|
||
|
if isinstance(a, types.UnicodeType):
|
||
|
from numba.cpython.unicode import _get_code_point
|
||
|
|
||
|
def impl(a):
|
||
|
if len(a) > 1:
|
||
|
msg = "gettyperecord takes a single unicode character"
|
||
|
raise ValueError(msg)
|
||
|
code_point = _get_code_point(a, 0)
|
||
|
data = _gettyperecord_impl(_Py_UCS4(code_point))
|
||
|
return data
|
||
|
return impl
|
||
|
if isinstance(a, types.Integer):
|
||
|
return lambda a: _gettyperecord_impl(_Py_UCS4(a))
|
||
|
|
||
|
|
||
|
# whilst it's possible to grab the _PyUnicode_ExtendedCase symbol as it's global
|
||
|
# it is safer to use a defined api:
|
||
|
@intrinsic
|
||
|
def _PyUnicode_ExtendedCase(typingctx, index):
|
||
|
"""
|
||
|
Accessor function for the _PyUnicode_ExtendedCase array, binds to
|
||
|
numba_get_PyUnicode_ExtendedCase which wraps the array and does the lookup
|
||
|
"""
|
||
|
if not isinstance(index, types.Integer):
|
||
|
raise TypingError("Expected an index")
|
||
|
|
||
|
def details(context, builder, signature, args):
|
||
|
ll_Py_UCS4 = context.get_value_type(_Py_UCS4)
|
||
|
ll_intc = context.get_value_type(types.intc)
|
||
|
fnty = llvmlite.ir.FunctionType(ll_Py_UCS4, [ll_intc])
|
||
|
fn = cgutils.get_or_insert_function(
|
||
|
builder.module,
|
||
|
fnty, name="numba_get_PyUnicode_ExtendedCase")
|
||
|
return builder.call(fn, [args[0]])
|
||
|
|
||
|
sig = _Py_UCS4(types.intc)
|
||
|
return sig, details
|
||
|
|
||
|
# The following functions are replications of the functions with the same name
|
||
|
# in CPython's Objects/unicodectype.c
|
||
|
|
||
|
|
||
|
# From: https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Objects/unicodectype.c#L64-L71 # noqa: E501
|
||
|
@register_jitable
|
||
|
def _PyUnicode_ToTitlecase(ch):
|
||
|
ctype = _PyUnicode_gettyperecord(ch)
|
||
|
if (ctype.flags & _PyUnicode_TyperecordMasks.EXTENDED_CASE_MASK):
|
||
|
return _PyUnicode_ExtendedCase(ctype.title & 0xFFFF)
|
||
|
return ch + ctype.title
|
||
|
|
||
|
|
||
|
# From: https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Objects/unicodectype.c#L76-L81 # noqa: E501
|
||
|
@register_jitable
|
||
|
def _PyUnicode_IsTitlecase(ch):
|
||
|
ctype = _PyUnicode_gettyperecord(ch)
|
||
|
return ctype.flags & _PyUnicode_TyperecordMasks.TITLE_MASK != 0
|
||
|
|
||
|
|
||
|
# From: https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Objects/unicodectype.c#L86-L91 # noqa: E501
|
||
|
@register_jitable
|
||
|
def _PyUnicode_IsXidStart(ch):
|
||
|
ctype = _PyUnicode_gettyperecord(ch)
|
||
|
return ctype.flags & _PyUnicode_TyperecordMasks.XID_START_MASK != 0
|
||
|
|
||
|
|
||
|
# From: https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Objects/unicodectype.c#L96-L101 # noqa: E501
|
||
|
@register_jitable
|
||
|
def _PyUnicode_IsXidContinue(ch):
|
||
|
ctype = _PyUnicode_gettyperecord(ch)
|
||
|
return ctype.flags & _PyUnicode_TyperecordMasks.XID_CONTINUE_MASK != 0
|
||
|
|
||
|
|
||
|
@register_jitable
|
||
|
def _PyUnicode_ToDecimalDigit(ch):
|
||
|
ctype = _PyUnicode_gettyperecord(ch)
|
||
|
if ctype.flags & _PyUnicode_TyperecordMasks.DECIMAL_MASK:
|
||
|
return ctype.decimal
|
||
|
return -1
|
||
|
|
||
|
|
||
|
# From: https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Objects/unicodectype.c#L123-L1128 # noqa: E501
|
||
|
@register_jitable
|
||
|
def _PyUnicode_ToDigit(ch):
|
||
|
ctype = _PyUnicode_gettyperecord(ch)
|
||
|
if ctype.flags & _PyUnicode_TyperecordMasks.DIGIT_MASK:
|
||
|
return ctype.digit
|
||
|
return -1
|
||
|
|
||
|
|
||
|
# From: https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Objects/unicodectype.c#L140-L145 # noqa: E501
|
||
|
@register_jitable
|
||
|
def _PyUnicode_IsNumeric(ch):
|
||
|
ctype = _PyUnicode_gettyperecord(ch)
|
||
|
return ctype.flags & _PyUnicode_TyperecordMasks.NUMERIC_MASK != 0
|
||
|
|
||
|
|
||
|
# From: https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Objects/unicodectype.c#L160-L165 # noqa: E501
|
||
|
@register_jitable
|
||
|
def _PyUnicode_IsPrintable(ch):
|
||
|
ctype = _PyUnicode_gettyperecord(ch)
|
||
|
return ctype.flags & _PyUnicode_TyperecordMasks.PRINTABLE_MASK != 0
|
||
|
|
||
|
|
||
|
# From: https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Objects/unicodectype.c#L170-L175 # noqa: E501
|
||
|
@register_jitable
|
||
|
def _PyUnicode_IsLowercase(ch):
|
||
|
ctype = _PyUnicode_gettyperecord(ch)
|
||
|
return ctype.flags & _PyUnicode_TyperecordMasks.LOWER_MASK != 0
|
||
|
|
||
|
|
||
|
# From: https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Objects/unicodectype.c#L180-L185 # noqa: E501
|
||
|
@register_jitable
|
||
|
def _PyUnicode_IsUppercase(ch):
|
||
|
ctype = _PyUnicode_gettyperecord(ch)
|
||
|
return ctype.flags & _PyUnicode_TyperecordMasks.UPPER_MASK != 0
|
||
|
|
||
|
|
||
|
@register_jitable
|
||
|
def _PyUnicode_IsLineBreak(ch):
|
||
|
ctype = _PyUnicode_gettyperecord(ch)
|
||
|
return ctype.flags & _PyUnicode_TyperecordMasks.LINEBREAK_MASK != 0
|
||
|
|
||
|
|
||
|
@register_jitable
|
||
|
def _PyUnicode_ToUppercase(ch):
|
||
|
raise NotImplementedError
|
||
|
|
||
|
|
||
|
@register_jitable
|
||
|
def _PyUnicode_ToLowercase(ch):
|
||
|
raise NotImplementedError
|
||
|
|
||
|
|
||
|
# From: https://github.com/python/cpython/blob/201c8f79450628241574fba940e08107178dc3a5/Objects/unicodectype.c#L211-L225 # noqa: E501
|
||
|
@register_jitable
|
||
|
def _PyUnicode_ToLowerFull(ch, res):
|
||
|
ctype = _PyUnicode_gettyperecord(ch)
|
||
|
if (ctype.flags & _PyUnicode_TyperecordMasks.EXTENDED_CASE_MASK):
|
||
|
index = ctype.lower & 0xFFFF
|
||
|
n = ctype.lower >> 24
|
||
|
for i in range(n):
|
||
|
res[i] = _PyUnicode_ExtendedCase(index + i)
|
||
|
return n
|
||
|
res[0] = ch + ctype.lower
|
||
|
return 1
|
||
|
|
||
|
|
||
|
# From: https://github.com/python/cpython/blob/201c8f79450628241574fba940e08107178dc3a5/Objects/unicodectype.c#L227-L241 # noqa: E501
|
||
|
@register_jitable
|
||
|
def _PyUnicode_ToTitleFull(ch, res):
|
||
|
ctype = _PyUnicode_gettyperecord(ch)
|
||
|
if (ctype.flags & _PyUnicode_TyperecordMasks.EXTENDED_CASE_MASK):
|
||
|
index = ctype.title & 0xFFFF
|
||
|
n = ctype.title >> 24
|
||
|
for i in range(n):
|
||
|
res[i] = _PyUnicode_ExtendedCase(index + i)
|
||
|
return n
|
||
|
res[0] = ch + ctype.title
|
||
|
return 1
|
||
|
|
||
|
|
||
|
# From: https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Objects/unicodectype.c#L243-L257 # noqa: E501
|
||
|
@register_jitable
|
||
|
def _PyUnicode_ToUpperFull(ch, res):
|
||
|
ctype = _PyUnicode_gettyperecord(ch)
|
||
|
if (ctype.flags & _PyUnicode_TyperecordMasks.EXTENDED_CASE_MASK):
|
||
|
index = ctype.upper & 0xFFFF
|
||
|
n = ctype.upper >> 24
|
||
|
for i in range(n):
|
||
|
# Perhaps needed to use unicode._set_code_point() here
|
||
|
res[i] = _PyUnicode_ExtendedCase(index + i)
|
||
|
return n
|
||
|
res[0] = ch + ctype.upper
|
||
|
return 1
|
||
|
|
||
|
|
||
|
# From: https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Objects/unicodectype.c#L259-L272 # noqa: E501
|
||
|
@register_jitable
|
||
|
def _PyUnicode_ToFoldedFull(ch, res):
|
||
|
ctype = _PyUnicode_gettyperecord(ch)
|
||
|
extended_case_mask = _PyUnicode_TyperecordMasks.EXTENDED_CASE_MASK
|
||
|
if ctype.flags & extended_case_mask and (ctype.lower >> 20) & 7:
|
||
|
index = (ctype.lower & 0xFFFF) + (ctype.lower >> 24)
|
||
|
n = (ctype.lower >> 20) & 7
|
||
|
for i in range(n):
|
||
|
res[i] = _PyUnicode_ExtendedCase(index + i)
|
||
|
return n
|
||
|
return _PyUnicode_ToLowerFull(ch, res)
|
||
|
|
||
|
|
||
|
# From: https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Objects/unicodectype.c#L274-L279 # noqa: E501
|
||
|
@register_jitable
|
||
|
def _PyUnicode_IsCased(ch):
|
||
|
ctype = _PyUnicode_gettyperecord(ch)
|
||
|
return ctype.flags & _PyUnicode_TyperecordMasks.CASED_MASK != 0
|
||
|
|
||
|
|
||
|
# From: https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Objects/unicodectype.c#L281-L286 # noqa: E501
|
||
|
@register_jitable
|
||
|
def _PyUnicode_IsCaseIgnorable(ch):
|
||
|
ctype = _PyUnicode_gettyperecord(ch)
|
||
|
return ctype.flags & _PyUnicode_TyperecordMasks.CASE_IGNORABLE_MASK != 0
|
||
|
|
||
|
|
||
|
# From: https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Objects/unicodectype.c#L123-L135 # noqa: E501
|
||
|
@register_jitable
|
||
|
def _PyUnicode_IsDigit(ch):
|
||
|
if _PyUnicode_ToDigit(ch) < 0:
|
||
|
return 0
|
||
|
return 1
|
||
|
|
||
|
|
||
|
# From: https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Objects/unicodectype.c#L106-L118 # noqa: E501
|
||
|
@register_jitable
|
||
|
def _PyUnicode_IsDecimalDigit(ch):
|
||
|
if _PyUnicode_ToDecimalDigit(ch) < 0:
|
||
|
return 0
|
||
|
return 1
|
||
|
|
||
|
|
||
|
# From: https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Objects/unicodectype.c#L291-L296 # noqa: E501
|
||
|
@register_jitable
|
||
|
def _PyUnicode_IsSpace(ch):
|
||
|
ctype = _PyUnicode_gettyperecord(ch)
|
||
|
return ctype.flags & _PyUnicode_TyperecordMasks.SPACE_MASK != 0
|
||
|
|
||
|
|
||
|
@register_jitable
|
||
|
def _PyUnicode_IsAlpha(ch):
|
||
|
ctype = _PyUnicode_gettyperecord(ch)
|
||
|
return ctype.flags & _PyUnicode_TyperecordMasks.ALPHA_MASK != 0
|
||
|
|
||
|
|
||
|
# End code related to/from CPython's unicodectype impl
|
||
|
# ------------------------------------------------------------------------------
|
||
|
|
||
|
|
||
|
# ------------------------------------------------------------------------------
|
||
|
# Start code related to/from CPython's pyctype
|
||
|
|
||
|
# From the definition in CPython's Include/pyctype.h
|
||
|
# From: https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Include/pyctype.h#L5-L11 # noqa: E501
|
||
|
class _PY_CTF(IntEnum):
|
||
|
LOWER = 0x01
|
||
|
UPPER = 0x02
|
||
|
ALPHA = 0x01 | 0x02
|
||
|
DIGIT = 0x04
|
||
|
ALNUM = 0x01 | 0x02 | 0x04
|
||
|
SPACE = 0x08
|
||
|
XDIGIT = 0x10
|
||
|
|
||
|
|
||
|
# From the definition in CPython's Python/pyctype.c
|
||
|
# https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Python/pyctype.c#L5 # noqa: E501
|
||
|
_Py_ctype_table = np.array([
|
||
|
0, # 0x0 '\x00'
|
||
|
0, # 0x1 '\x01'
|
||
|
0, # 0x2 '\x02'
|
||
|
0, # 0x3 '\x03'
|
||
|
0, # 0x4 '\x04'
|
||
|
0, # 0x5 '\x05'
|
||
|
0, # 0x6 '\x06'
|
||
|
0, # 0x7 '\x07'
|
||
|
0, # 0x8 '\x08'
|
||
|
_PY_CTF.SPACE, # 0x9 '\t'
|
||
|
_PY_CTF.SPACE, # 0xa '\n'
|
||
|
_PY_CTF.SPACE, # 0xb '\v'
|
||
|
_PY_CTF.SPACE, # 0xc '\f'
|
||
|
_PY_CTF.SPACE, # 0xd '\r'
|
||
|
0, # 0xe '\x0e'
|
||
|
0, # 0xf '\x0f'
|
||
|
0, # 0x10 '\x10'
|
||
|
0, # 0x11 '\x11'
|
||
|
0, # 0x12 '\x12'
|
||
|
0, # 0x13 '\x13'
|
||
|
0, # 0x14 '\x14'
|
||
|
0, # 0x15 '\x15'
|
||
|
0, # 0x16 '\x16'
|
||
|
0, # 0x17 '\x17'
|
||
|
0, # 0x18 '\x18'
|
||
|
0, # 0x19 '\x19'
|
||
|
0, # 0x1a '\x1a'
|
||
|
0, # 0x1b '\x1b'
|
||
|
0, # 0x1c '\x1c'
|
||
|
0, # 0x1d '\x1d'
|
||
|
0, # 0x1e '\x1e'
|
||
|
0, # 0x1f '\x1f'
|
||
|
_PY_CTF.SPACE, # 0x20 ' '
|
||
|
0, # 0x21 '!'
|
||
|
0, # 0x22 '"'
|
||
|
0, # 0x23 '#'
|
||
|
0, # 0x24 '$'
|
||
|
0, # 0x25 '%'
|
||
|
0, # 0x26 '&'
|
||
|
0, # 0x27 "'"
|
||
|
0, # 0x28 '('
|
||
|
0, # 0x29 ')'
|
||
|
0, # 0x2a '*'
|
||
|
0, # 0x2b '+'
|
||
|
0, # 0x2c ','
|
||
|
0, # 0x2d '-'
|
||
|
0, # 0x2e '.'
|
||
|
0, # 0x2f '/'
|
||
|
_PY_CTF.DIGIT | _PY_CTF.XDIGIT, # 0x30 '0'
|
||
|
_PY_CTF.DIGIT | _PY_CTF.XDIGIT, # 0x31 '1'
|
||
|
_PY_CTF.DIGIT | _PY_CTF.XDIGIT, # 0x32 '2'
|
||
|
_PY_CTF.DIGIT | _PY_CTF.XDIGIT, # 0x33 '3'
|
||
|
_PY_CTF.DIGIT | _PY_CTF.XDIGIT, # 0x34 '4'
|
||
|
_PY_CTF.DIGIT | _PY_CTF.XDIGIT, # 0x35 '5'
|
||
|
_PY_CTF.DIGIT | _PY_CTF.XDIGIT, # 0x36 '6'
|
||
|
_PY_CTF.DIGIT | _PY_CTF.XDIGIT, # 0x37 '7'
|
||
|
_PY_CTF.DIGIT | _PY_CTF.XDIGIT, # 0x38 '8'
|
||
|
_PY_CTF.DIGIT | _PY_CTF.XDIGIT, # 0x39 '9'
|
||
|
0, # 0x3a ':'
|
||
|
0, # 0x3b ';'
|
||
|
0, # 0x3c '<'
|
||
|
0, # 0x3d '='
|
||
|
0, # 0x3e '>'
|
||
|
0, # 0x3f '?'
|
||
|
0, # 0x40 '@'
|
||
|
_PY_CTF.UPPER | _PY_CTF.XDIGIT, # 0x41 'A'
|
||
|
_PY_CTF.UPPER | _PY_CTF.XDIGIT, # 0x42 'B'
|
||
|
_PY_CTF.UPPER | _PY_CTF.XDIGIT, # 0x43 'C'
|
||
|
_PY_CTF.UPPER | _PY_CTF.XDIGIT, # 0x44 'D'
|
||
|
_PY_CTF.UPPER | _PY_CTF.XDIGIT, # 0x45 'E'
|
||
|
_PY_CTF.UPPER | _PY_CTF.XDIGIT, # 0x46 'F'
|
||
|
_PY_CTF.UPPER, # 0x47 'G'
|
||
|
_PY_CTF.UPPER, # 0x48 'H'
|
||
|
_PY_CTF.UPPER, # 0x49 'I'
|
||
|
_PY_CTF.UPPER, # 0x4a 'J'
|
||
|
_PY_CTF.UPPER, # 0x4b 'K'
|
||
|
_PY_CTF.UPPER, # 0x4c 'L'
|
||
|
_PY_CTF.UPPER, # 0x4d 'M'
|
||
|
_PY_CTF.UPPER, # 0x4e 'N'
|
||
|
_PY_CTF.UPPER, # 0x4f 'O'
|
||
|
_PY_CTF.UPPER, # 0x50 'P'
|
||
|
_PY_CTF.UPPER, # 0x51 'Q'
|
||
|
_PY_CTF.UPPER, # 0x52 'R'
|
||
|
_PY_CTF.UPPER, # 0x53 'S'
|
||
|
_PY_CTF.UPPER, # 0x54 'T'
|
||
|
_PY_CTF.UPPER, # 0x55 'U'
|
||
|
_PY_CTF.UPPER, # 0x56 'V'
|
||
|
_PY_CTF.UPPER, # 0x57 'W'
|
||
|
_PY_CTF.UPPER, # 0x58 'X'
|
||
|
_PY_CTF.UPPER, # 0x59 'Y'
|
||
|
_PY_CTF.UPPER, # 0x5a 'Z'
|
||
|
0, # 0x5b '['
|
||
|
0, # 0x5c '\\'
|
||
|
0, # 0x5d ']'
|
||
|
0, # 0x5e '^'
|
||
|
0, # 0x5f '_'
|
||
|
0, # 0x60 '`'
|
||
|
_PY_CTF.LOWER | _PY_CTF.XDIGIT, # 0x61 'a'
|
||
|
_PY_CTF.LOWER | _PY_CTF.XDIGIT, # 0x62 'b'
|
||
|
_PY_CTF.LOWER | _PY_CTF.XDIGIT, # 0x63 'c'
|
||
|
_PY_CTF.LOWER | _PY_CTF.XDIGIT, # 0x64 'd'
|
||
|
_PY_CTF.LOWER | _PY_CTF.XDIGIT, # 0x65 'e'
|
||
|
_PY_CTF.LOWER | _PY_CTF.XDIGIT, # 0x66 'f'
|
||
|
_PY_CTF.LOWER, # 0x67 'g'
|
||
|
_PY_CTF.LOWER, # 0x68 'h'
|
||
|
_PY_CTF.LOWER, # 0x69 'i'
|
||
|
_PY_CTF.LOWER, # 0x6a 'j'
|
||
|
_PY_CTF.LOWER, # 0x6b 'k'
|
||
|
_PY_CTF.LOWER, # 0x6c 'l'
|
||
|
_PY_CTF.LOWER, # 0x6d 'm'
|
||
|
_PY_CTF.LOWER, # 0x6e 'n'
|
||
|
_PY_CTF.LOWER, # 0x6f 'o'
|
||
|
_PY_CTF.LOWER, # 0x70 'p'
|
||
|
_PY_CTF.LOWER, # 0x71 'q'
|
||
|
_PY_CTF.LOWER, # 0x72 'r'
|
||
|
_PY_CTF.LOWER, # 0x73 's'
|
||
|
_PY_CTF.LOWER, # 0x74 't'
|
||
|
_PY_CTF.LOWER, # 0x75 'u'
|
||
|
_PY_CTF.LOWER, # 0x76 'v'
|
||
|
_PY_CTF.LOWER, # 0x77 'w'
|
||
|
_PY_CTF.LOWER, # 0x78 'x'
|
||
|
_PY_CTF.LOWER, # 0x79 'y'
|
||
|
_PY_CTF.LOWER, # 0x7a 'z'
|
||
|
0, # 0x7b '{'
|
||
|
0, # 0x7c '|'
|
||
|
0, # 0x7d '}'
|
||
|
0, # 0x7e '~'
|
||
|
0, # 0x7f '\x7f'
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
], dtype=np.intc)
|
||
|
|
||
|
|
||
|
# From the definition in CPython's Python/pyctype.c
|
||
|
# https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Python/pyctype.c#L145 # noqa: E501
|
||
|
_Py_ctype_tolower = np.array([
|
||
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||
|
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||
|
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
||
|
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||
|
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
|
||
|
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
|
||
|
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
|
||
|
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
|
||
|
0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
|
||
|
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
|
||
|
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
|
||
|
0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
|
||
|
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
|
||
|
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
|
||
|
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
|
||
|
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
|
||
|
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
|
||
|
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
|
||
|
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
|
||
|
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
|
||
|
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
|
||
|
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
|
||
|
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
|
||
|
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
|
||
|
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
|
||
|
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
|
||
|
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
|
||
|
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
|
||
|
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
|
||
|
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
|
||
|
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
|
||
|
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
|
||
|
], dtype=np.uint8)
|
||
|
|
||
|
|
||
|
# From the definition in CPython's Python/pyctype.c
|
||
|
# https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Python/pyctype.c#L180
|
||
|
_Py_ctype_toupper = np.array([
|
||
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||
|
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||
|
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
||
|
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||
|
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
|
||
|
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
|
||
|
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
|
||
|
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
|
||
|
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
|
||
|
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
|
||
|
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
|
||
|
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
|
||
|
0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
|
||
|
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
|
||
|
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
|
||
|
0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
|
||
|
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
|
||
|
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
|
||
|
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
|
||
|
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
|
||
|
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
|
||
|
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
|
||
|
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
|
||
|
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
|
||
|
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
|
||
|
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
|
||
|
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
|
||
|
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
|
||
|
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
|
||
|
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
|
||
|
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
|
||
|
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
|
||
|
], dtype=np.uint8)
|
||
|
|
||
|
|
||
|
class _PY_CTF_LB(IntEnum):
|
||
|
LINE_BREAK = 0x01
|
||
|
LINE_FEED = 0x02
|
||
|
CARRIAGE_RETURN = 0x04
|
||
|
|
||
|
|
||
|
_Py_ctype_islinebreak = np.array([
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
_PY_CTF_LB.LINE_BREAK | _PY_CTF_LB.LINE_FEED, # 0xa '\n'
|
||
|
_PY_CTF_LB.LINE_BREAK, # 0xb '\v'
|
||
|
_PY_CTF_LB.LINE_BREAK, # 0xc '\f'
|
||
|
_PY_CTF_LB.LINE_BREAK | _PY_CTF_LB.CARRIAGE_RETURN, # 0xd '\r'
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
_PY_CTF_LB.LINE_BREAK, # 0x1c '\x1c'
|
||
|
_PY_CTF_LB.LINE_BREAK, # 0x1d '\x1d'
|
||
|
_PY_CTF_LB.LINE_BREAK, # 0x1e '\x1e'
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
_PY_CTF_LB.LINE_BREAK, # 0x85 '\x85'
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
0, 0, 0,
|
||
|
], dtype=np.intc)
|
||
|
|
||
|
|
||
|
# Translation of:
|
||
|
# https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Include/pymacro.h#L25 # noqa: E501
|
||
|
@register_jitable
|
||
|
def _Py_CHARMASK(ch):
|
||
|
"""
|
||
|
Equivalent to the CPython macro `Py_CHARMASK()`, masks off all but the
|
||
|
lowest 256 bits of ch.
|
||
|
"""
|
||
|
return types.uint8(ch) & types.uint8(0xff)
|
||
|
|
||
|
|
||
|
# Translation of:
|
||
|
# https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Include/pyctype.h#L30 # noqa: E501
|
||
|
@register_jitable
|
||
|
def _Py_TOUPPER(ch):
|
||
|
"""
|
||
|
Equivalent to the CPython macro `Py_TOUPPER()` converts an ASCII range
|
||
|
code point to the upper equivalent
|
||
|
"""
|
||
|
return _Py_ctype_toupper[_Py_CHARMASK(ch)]
|
||
|
|
||
|
|
||
|
# Translation of:
|
||
|
# https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Include/pyctype.h#L29 # noqa: E501
|
||
|
@register_jitable
|
||
|
def _Py_TOLOWER(ch):
|
||
|
"""
|
||
|
Equivalent to the CPython macro `Py_TOLOWER()` converts an ASCII range
|
||
|
code point to the lower equivalent
|
||
|
"""
|
||
|
return _Py_ctype_tolower[_Py_CHARMASK(ch)]
|
||
|
|
||
|
|
||
|
# Translation of:
|
||
|
# https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Include/pyctype.h#L18 # noqa: E501
|
||
|
@register_jitable
|
||
|
def _Py_ISLOWER(ch):
|
||
|
"""
|
||
|
Equivalent to the CPython macro `Py_ISLOWER()`
|
||
|
"""
|
||
|
return _Py_ctype_table[_Py_CHARMASK(ch)] & _PY_CTF.LOWER
|
||
|
|
||
|
|
||
|
# Translation of:
|
||
|
# https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Include/pyctype.h#L19 # noqa: E501
|
||
|
@register_jitable
|
||
|
def _Py_ISUPPER(ch):
|
||
|
"""
|
||
|
Equivalent to the CPython macro `Py_ISUPPER()`
|
||
|
"""
|
||
|
return _Py_ctype_table[_Py_CHARMASK(ch)] & _PY_CTF.UPPER
|
||
|
|
||
|
|
||
|
# Translation of:
|
||
|
# https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Include/pyctype.h#L20 # noqa: E501
|
||
|
@register_jitable
|
||
|
def _Py_ISALPHA(ch):
|
||
|
"""
|
||
|
Equivalent to the CPython macro `Py_ISALPHA()`
|
||
|
"""
|
||
|
return _Py_ctype_table[_Py_CHARMASK(ch)] & _PY_CTF.ALPHA
|
||
|
|
||
|
|
||
|
# Translation of:
|
||
|
# https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Include/pyctype.h#L21 # noqa: E501
|
||
|
@register_jitable
|
||
|
def _Py_ISDIGIT(ch):
|
||
|
"""
|
||
|
Equivalent to the CPython macro `Py_ISDIGIT()`
|
||
|
"""
|
||
|
return _Py_ctype_table[_Py_CHARMASK(ch)] & _PY_CTF.DIGIT
|
||
|
|
||
|
|
||
|
# Translation of:
|
||
|
# https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Include/pyctype.h#L22 # noqa: E501
|
||
|
@register_jitable
|
||
|
def _Py_ISXDIGIT(ch):
|
||
|
"""
|
||
|
Equivalent to the CPython macro `Py_ISXDIGIT()`
|
||
|
"""
|
||
|
return _Py_ctype_table[_Py_CHARMASK(ch)] & _PY_CTF.XDIGIT
|
||
|
|
||
|
|
||
|
# Translation of:
|
||
|
# https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Include/pyctype.h#L23 # noqa: E501
|
||
|
@register_jitable
|
||
|
def _Py_ISALNUM(ch):
|
||
|
"""
|
||
|
Equivalent to the CPython macro `Py_ISALNUM()`
|
||
|
"""
|
||
|
return _Py_ctype_table[_Py_CHARMASK(ch)] & _PY_CTF.ALNUM
|
||
|
|
||
|
|
||
|
# Translation of:
|
||
|
# https://github.com/python/cpython/blob/1d4b6ba19466aba0eb91c4ba01ba509acf18c723/Include/pyctype.h#L24 # noqa: E501
|
||
|
@register_jitable
|
||
|
def _Py_ISSPACE(ch):
|
||
|
"""
|
||
|
Equivalent to the CPython macro `Py_ISSPACE()`
|
||
|
"""
|
||
|
return _Py_ctype_table[_Py_CHARMASK(ch)] & _PY_CTF.SPACE
|
||
|
|
||
|
|
||
|
@register_jitable
|
||
|
def _Py_ISLINEBREAK(ch):
|
||
|
"""Check if character is ASCII line break"""
|
||
|
return _Py_ctype_islinebreak[_Py_CHARMASK(ch)] & _PY_CTF_LB.LINE_BREAK
|
||
|
|
||
|
|
||
|
@register_jitable
|
||
|
def _Py_ISLINEFEED(ch):
|
||
|
"""Check if character is line feed `\n`"""
|
||
|
return _Py_ctype_islinebreak[_Py_CHARMASK(ch)] & _PY_CTF_LB.LINE_FEED
|
||
|
|
||
|
|
||
|
@register_jitable
|
||
|
def _Py_ISCARRIAGERETURN(ch):
|
||
|
"""Check if character is carriage return `\r`"""
|
||
|
return _Py_ctype_islinebreak[_Py_CHARMASK(ch)] & _PY_CTF_LB.CARRIAGE_RETURN
|
||
|
|
||
|
|
||
|
# End code related to/from CPython's pyctype
|
||
|
# ------------------------------------------------------------------------------
|