LCOV - code coverage report
Current view: | top level - Modules - unicodedata.c (source / functions) |  |  | Hit | Total | Coverage
Test: | CPython 3.12 LCOV report [commit 5e6661bce9] |  | Lines: | 46 | 623 | 7.4 %
Date: | 2023-03-20 08:15:36 |  | Functions: | 7 | 35 | 20.0 %
|  |  | Branches: | 12 | 453 | 2.6 %

               Branch data     Line data    Source code
           1                 :            : /* ------------------------------------------------------------------------
           2                 :            :
           3                 :            :    unicodedata -- Provides access to the Unicode database.
           4                 :            :
           5                 :            :    The current version number is reported in the unidata_version constant.
           6                 :            :
           7                 :            :    Written by Marc-Andre Lemburg (mal@lemburg.com).
           8                 :            :    Modified for Python 2.0 by Fredrik Lundh (fredrik@pythonware.com)
           9                 :            :    Modified by Martin v. Löwis (martin@v.loewis.de)
          10                 :            :
          11                 :            :    Copyright (c) Corporation for National Research Initiatives.
          12                 :            :
          13                 :            :    ------------------------------------------------------------------------ */
          14                 :            :
          15                 :            : #ifndef Py_BUILD_CORE_BUILTIN
          16                 :            : #  define Py_BUILD_CORE_MODULE 1
          17                 :            : #endif
          18                 :            :
          19                 :            : #define PY_SSIZE_T_CLEAN
          20                 :            :
          21                 :            : #include "Python.h"
          22                 :            : #include "pycore_ucnhash.h"       // _PyUnicode_Name_CAPI
          23                 :            : #include "structmember.h"         // PyMemberDef
          24                 :            :
          25                 :            : #include <stdbool.h>
          26                 :            :
          27                 :            : /*[clinic input]
          28                 :            : module unicodedata
          29                 :            : class unicodedata.UCD 'PreviousDBVersion *' '<not used>'
          30                 :            : [clinic start generated code]*/
          31                 :            : /*[clinic end generated code: output=da39a3ee5e6b4b0d input=e47113e05924be43]*/
          32                 :            :
          33                 :            : /* character properties */
          34                 :            :
          35                 :            : typedef struct {
          36                 :            :     const unsigned char category;       /* index into
          37                 :            :                                            _PyUnicode_CategoryNames */
          38                 :            :     const unsigned char combining;      /* combining class value 0 - 255 */
          39                 :            :     const unsigned char bidirectional;  /* index into
          40                 :            :                                            _PyUnicode_BidirectionalNames */
          41                 :            :     const unsigned char mirrored;       /* true if mirrored in bidir mode */
          42                 :            :     const unsigned char east_asian_width;       /* index into
          43                 :            :                                                    _PyUnicode_EastAsianWidth */
          44                 :            :     const unsigned char normalization_quick_check; /* see is_normalized() */
          45                 :            : } _PyUnicode_DatabaseRecord;
          46                 :            :
          47                 :            : typedef struct change_record {
          48                 :            :     /* sequence of fields should be the same as in merge_old_version */
          49                 :            :     const unsigned char bidir_changed;
          50                 :            :     const unsigned char category_changed;
          51                 :            :     const unsigned char decimal_changed;
          52                 :            :     const unsigned char mirrored_changed;
          53                 :            :     const unsigned char east_asian_width_changed;
          54                 :            :     const double numeric_changed;
          55                 :            : } change_record;
          56                 :            :
          57                 :            : /* data file generated by Tools/unicode/makeunicodedata.py */
          58                 :            : #include "unicodedata_db.h"
          59                 :            :
          60                 :            : static const _PyUnicode_DatabaseRecord*
          61                 :          0 : _getrecord_ex(Py_UCS4 code)
          62                 :            : {
          63                 :            :     int index;
          64         [ #  # ]:          0 :     if (code >= 0x110000)
          65                 :          0 :         index = 0;
          66                 :            :     else {
          67                 :          0 :         index = index1[(code>>SHIFT)];
          68                 :          0 :         index = index2[(index<<SHIFT)+(code&((1<<SHIFT)-1))];
          69                 :            :     }
          70                 :            :
          71                 :          0 :     return &_PyUnicode_Database_Records[index];
          72                 :            : }
          73                 :            :
          74                 :            : /* ------------- Previous-version API ------------------------------------- */
          75                 :            : typedef struct previous_version {
          76                 :            :     PyObject_HEAD
          77                 :            :     const char *name;
          78                 :            :     const change_record* (*getrecord)(Py_UCS4);
          79                 :            :     Py_UCS4 (*normalization)(Py_UCS4);
          80                 :            : } PreviousDBVersion;
          81                 :            :
          82                 :            : #include "clinic/unicodedata.c.h"
          83                 :            :
          84                 :            : #define get_old_record(self, v)    ((((PreviousDBVersion*)self)->getrecord)(v))
          85                 :            :
          86                 :            : static PyMemberDef DB_members[] = {
          87                 :            :         {"unidata_version", T_STRING, offsetof(PreviousDBVersion, name), READONLY},
          88                 :            :         {NULL}
          89                 :            : };
          90                 :            :
          91                 :            : // Check if self is an unicodedata.UCD instance.
          92                 :            : // If self is NULL (when the PyCapsule C API is used), return 0.
          93                 :            : // PyModule_Check() is used to avoid having to retrieve the ucd_type.
          94                 :            : // See unicodedata_functions comment to the rationale of this macro.
          95                 :            : #define UCD_Check(self) (self != NULL && !PyModule_Check(self))
          96                 :            :
          97                 :            : static PyObject*
          98                 :          1 : new_previous_version(PyTypeObject *ucd_type,
          99                 :            :                      const char*name, const change_record* (*getrecord)(Py_UCS4),
         100                 :            :                      Py_UCS4 (*normalization)(Py_UCS4))
         101                 :            : {
         102                 :            :     PreviousDBVersion *self;
         103                 :          1 :     self = PyObject_GC_New(PreviousDBVersion, ucd_type);
         104         [ -  + ]:          1 :     if (self == NULL)
         105                 :          0 :         return NULL;
         106                 :          1 :     self->name = name;
         107                 :          1 :     self->getrecord = getrecord;
         108                 :          1 :     self->normalization = normalization;
         109                 :          1 :     PyObject_GC_Track(self);
         110                 :          1 :     return (PyObject*)self;
         111                 :            : }
         112                 :            :
         113                 :            :
         114                 :            : /* --- Module API --------------------------------------------------------- */
         115                 :            :
         116                 :            : /*[clinic input]
         117                 :            : unicodedata.UCD.decimal
         118                 :            :
         119                 :            :     self: self
         120                 :            :     chr: int(accept={str})
         121                 :            :     default: object=NULL
         122                 :            :     /
         123                 :            :
         124                 :            : Converts a Unicode character into its equivalent decimal value.
         125                 :            :
         126                 :            : Returns the decimal value assigned to the character chr as integer.
         127                 :            : If no such value is defined, default is returned, or, if not given,
         128                 :            : ValueError is raised.
         129                 :            : [clinic start generated code]*/
         130                 :            :
         131                 :            : static PyObject *
         132                 :          0 : unicodedata_UCD_decimal_impl(PyObject *self, int chr,
         133                 :            :                              PyObject *default_value)
         134                 :            : /*[clinic end generated code: output=be23376e1a185231 input=933f8107993f23d0]*/
         135                 :            : {
         136                 :          0 :     int have_old = 0;
         137                 :            :     long rc;
         138                 :          0 :     Py_UCS4 c = (Py_UCS4)chr;
         139                 :            :
         140   [ #  #  #  # ]:          0 :     if (UCD_Check(self)) {
         141                 :          0 :         const change_record *old = get_old_record(self, c);
         142         [ #  # ]:          0 :         if (old->category_changed == 0) {
         143                 :            :             /* unassigned */
         144                 :          0 :             have_old = 1;
         145                 :          0 :             rc = -1;
         146                 :            :         }
         147         [ #  # ]:          0 :         else if (old->decimal_changed != 0xFF) {
         148                 :          0 :             have_old = 1;
         149                 :          0 :             rc = old->decimal_changed;
         150                 :            :         }
         151                 :            :     }
         152                 :            :
         153         [ #  # ]:          0 :     if (!have_old)
         154                 :          0 :         rc = Py_UNICODE_TODECIMAL(c);
         155         [ #  # ]:          0 :     if (rc < 0) {
         156         [ #  # ]:          0 :         if (default_value == NULL) {
         157                 :          0 :             PyErr_SetString(PyExc_ValueError,
         158                 :            :                             "not a decimal");
         159                 :          0 :             return NULL;
         160                 :            :         }
         161                 :            :         else {
         162                 :          0 :             return Py_NewRef(default_value);
         163                 :            :         }
         164                 :            :     }
         165                 :          0 :     return PyLong_FromLong(rc);
         166                 :            : }
         167                 :            :
         168                 :            : /*[clinic input]
         169                 :            : unicodedata.UCD.digit
         170                 :            :
         171                 :            :     self: self
         172                 :            :     chr: int(accept={str})
         173                 :            :     default: object=NULL
         174                 :            :     /
         175                 :            :
         176                 :            : Converts a Unicode character into its equivalent digit value.
         177                 :            :
         178                 :            : Returns the digit value assigned to the character chr as integer.
         179                 :            : If no such value is defined, default is returned, or, if not given,
         180                 :            : ValueError is raised.
         181                 :            : [clinic start generated code]*/
         182                 :            :
         183                 :            : static PyObject *
         184                 :          0 : unicodedata_UCD_digit_impl(PyObject *self, int chr, PyObject *default_value)
         185                 :            : /*[clinic end generated code: output=96e18c950171fd2f input=e27d6e4565cd29f2]*/
         186                 :            : {
         187                 :            :     long rc;
         188                 :          0 :     Py_UCS4 c = (Py_UCS4)chr;
         189                 :          0 :     rc = Py_UNICODE_TODIGIT(c);
         190         [ #  # ]:          0 :     if (rc < 0) {
         191         [ #  # ]:          0 :         if (default_value == NULL) {
         192                 :          0 :             PyErr_SetString(PyExc_ValueError, "not a digit");
         193                 :          0 :             return NULL;
         194                 :            :         }
         195                 :            :         else {
         196                 :          0 :             return Py_NewRef(default_value);
         197                 :            :         }
         198                 :            :     }
         199                 :          0 :     return PyLong_FromLong(rc);
         200                 :            : }
         201                 :            :
         202                 :            : /*[clinic input]
         203                 :            : unicodedata.UCD.numeric
         204                 :            :
         205                 :            :     self: self
         206                 :            :     chr: int(accept={str})
         207                 :            :     default: object=NULL
         208                 :            :     /
         209                 :            :
         210                 :            : Converts a Unicode character into its equivalent numeric value.
         211                 :            :
         212                 :            : Returns the numeric value assigned to the character chr as float.
         213                 :            : If no such value is defined, default is returned, or, if not given,
         214                 :            : ValueError is raised.
         215                 :            : [clinic start generated code]*/
         216                 :            :
         217                 :            : static PyObject *
         218                 :          0 : unicodedata_UCD_numeric_impl(PyObject *self, int chr,
         219                 :            :                              PyObject *default_value)
         220                 :            : /*[clinic end generated code: output=53ce281fe85b10c4 input=fdf5871a5542893c]*/
         221                 :            : {
         222                 :          0 :     int have_old = 0;
         223                 :            :     double rc;
         224                 :          0 :     Py_UCS4 c = (Py_UCS4)chr;
         225                 :            :
         226   [ #  #  #  # ]:          0 :     if (UCD_Check(self)) {
         227                 :          0 :         const change_record *old = get_old_record(self, c);
         228         [ #  # ]:          0 :         if (old->category_changed == 0) {
         229                 :            :             /* unassigned */
         230                 :          0 :             have_old = 1;
         231                 :          0 :             rc = -1.0;
         232                 :            :         }
         233         [ #  # ]:          0 :         else if (old->decimal_changed != 0xFF) {
         234                 :          0 :             have_old = 1;
         235                 :          0 :             rc = old->decimal_changed;
         236                 :            :         }
         237                 :            :     }
         238                 :            :
         239         [ #  # ]:          0 :     if (!have_old)
         240                 :          0 :         rc = Py_UNICODE_TONUMERIC(c);
         241         [ #  # ]:          0 :     if (rc == -1.0) {
         242         [ #  # ]:          0 :         if (default_value == NULL) {
         243                 :          0 :             PyErr_SetString(PyExc_ValueError, "not a numeric character");
         244                 :          0 :             return NULL;
         245                 :            :         }
         246                 :            :         else {
         247                 :          0 :             return Py_NewRef(default_value);
         248                 :            :         }
         249                 :            :     }
         250                 :          0 :     return PyFloat_FromDouble(rc);
         251                 :            : }
         252                 :            :
         253                 :            : /*[clinic input]
         254                 :            : unicodedata.UCD.category
         255                 :            :
         256                 :            :     self: self
         257                 :            :     chr: int(accept={str})
         258                 :            :     /
         259                 :            :
         260                 :            : Returns the general category assigned to the character chr as string.
         261                 :            : [clinic start generated code]*/
         262                 :            :
         263                 :            : static PyObject *
         264                 :          0 : unicodedata_UCD_category_impl(PyObject *self, int chr)
         265                 :            : /*[clinic end generated code: output=8571539ee2e6783a input=27d6f3d85050bc06]*/
         266                 :            : {
         267                 :            :     int index;
         268                 :          0 :     Py_UCS4 c = (Py_UCS4)chr;
         269                 :          0 :     index = (int) _getrecord_ex(c)->category;
         270   [ #  #  #  # ]:          0 :     if (UCD_Check(self)) {
         271                 :          0 :         const change_record *old = get_old_record(self, c);
         272         [ #  # ]:          0 :         if (old->category_changed != 0xFF)
         273                 :          0 :             index = old->category_changed;
         274                 :            :     }
         275                 :          0 :     return PyUnicode_FromString(_PyUnicode_CategoryNames[index]);
         276                 :            : }
         277                 :            :
         278                 :            : /*[clinic input]
         279                 :            : unicodedata.UCD.bidirectional
         280                 :            :
         281                 :            :     self: self
         282                 :            :     chr: int(accept={str})
         283                 :            :     /
         284                 :            :
         285                 :            : Returns the bidirectional class assigned to the character chr as string.
         286                 :            :
         287                 :            : If no such value is defined, an empty string is returned.
         288                 :            : [clinic start generated code]*/
         289                 :            :
         290                 :            : static PyObject *
         291                 :          0 : unicodedata_UCD_bidirectional_impl(PyObject *self, int chr)
         292                 :            : /*[clinic end generated code: output=d36310ce2039bb92 input=b3d8f42cebfcf475]*/
         293                 :            : {
         294                 :            :     int index;
         295                 :          0 :     Py_UCS4 c = (Py_UCS4)chr;
         296                 :          0 :     index = (int) _getrecord_ex(c)->bidirectional;
         297   [ #  #  #  # ]:          0 :     if (UCD_Check(self)) {
         298                 :          0 :         const change_record *old = get_old_record(self, c);
         299         [ #  # ]:          0 :         if (old->category_changed == 0)
         300                 :          0 :             index = 0; /* unassigned */
         301         [ #  # ]:          0 :         else if (old->bidir_changed != 0xFF)
         302                 :          0 :             index = old->bidir_changed;
         303                 :            :     }
         304                 :          0 :     return PyUnicode_FromString(_PyUnicode_BidirectionalNames[index]);
         305                 :            : }
         306                 :            :
         307                 :            : /*[clinic input]
         308                 :            : unicodedata.UCD.combining -> int
         309                 :            :
         310                 :            :     self: self
         311                 :            :     chr: int(accept={str})
         312                 :            :     /
         313                 :            :
         314                 :            : Returns the canonical combining class assigned to the character chr as integer.
         315                 :            :
         316                 :            : Returns 0 if no combining class is defined.
         317                 :            : [clinic start generated code]*/
         318                 :            :
         319                 :            : static int
         320                 :          0 : unicodedata_UCD_combining_impl(PyObject *self, int chr)
         321                 :            : /*[clinic end generated code: output=cad056d0cb6a5920 input=9f2d6b2a95d0a22a]*/
         322                 :            : {
         323                 :            :     int index;
         324                 :          0 :     Py_UCS4 c = (Py_UCS4)chr;
         325                 :          0 :     index = (int) _getrecord_ex(c)->combining;
         326   [ #  #  #  # ]:          0 :     if (UCD_Check(self)) {
         327                 :          0 :         const change_record *old = get_old_record(self, c);
         328         [ #  # ]:          0 :         if (old->category_changed == 0)
         329                 :          0 :             index = 0; /* unassigned */
         330                 :            :     }
         331                 :          0 :     return index;
         332                 :            : }
         333                 :            :
         334                 :            : /*[clinic input]
         335                 :            : unicodedata.UCD.mirrored -> int
         336                 :            :
         337                 :            :     self: self
         338                 :            :     chr: int(accept={str})
         339                 :            :     /
         340                 :            :
         341                 :            : Returns the mirrored property assigned to the character chr as integer.
         342                 :            :
         343                 :            : Returns 1 if the character has been identified as a "mirrored"
         344                 :            : character in bidirectional text, 0 otherwise.
         345                 :            : [clinic start generated code]*/
         346                 :            :
         347                 :            : static int
         348                 :          0 : unicodedata_UCD_mirrored_impl(PyObject *self, int chr)
         349                 :            : /*[clinic end generated code: output=2532dbf8121b50e6 input=5dd400d351ae6f3b]*/
         350                 :            : {
         351                 :            :     int index;
         352                 :          0 :     Py_UCS4 c = (Py_UCS4)chr;
         353                 :          0 :     index = (int) _getrecord_ex(c)->mirrored;
         354   [ #  #  #  # ]:          0 :     if (UCD_Check(self)) {
         355                 :          0 :         const change_record *old = get_old_record(self, c);
         356         [ #  # ]:          0 :         if (old->category_changed == 0)
         357                 :          0 :             index = 0; /* unassigned */
         358         [ #  # ]:          0 :         else if (old->mirrored_changed != 0xFF)
         359                 :          0 :             index = old->mirrored_changed;
         360                 :            :     }
         361                 :          0 :     return index;
         362                 :            : }
         363                 :            :
         364                 :            : /*[clinic input]
         365                 :            : unicodedata.UCD.east_asian_width
         366                 :            :
         367                 :            :     self: self
         368                 :            :     chr: int(accept={str})
         369                 :            :     /
         370                 :            :
         371                 :            : Returns the east asian width assigned to the character chr as string.
         372                 :            : [clinic start generated code]*/
         373                 :            :
         374                 :            : static PyObject *
         375                 :          0 : unicodedata_UCD_east_asian_width_impl(PyObject *self, int chr)
         376                 :            : /*[clinic end generated code: output=484e8537d9ee8197 input=c4854798aab026e0]*/
         377                 :            : {
         378                 :            :     int index;
         379                 :          0 :     Py_UCS4 c = (Py_UCS4)chr;
         380                 :          0 :     index = (int) _getrecord_ex(c)->east_asian_width;
         381   [ #  #  #  # ]:          0 :     if (UCD_Check(self)) {
         382                 :          0 :         const change_record *old = get_old_record(self, c);
         383         [ #  # ]:          0 :         if (old->category_changed == 0)
         384                 :          0 :             index = 0; /* unassigned */
         385         [ #  # ]:          0 :         else if (old->east_asian_width_changed != 0xFF)
         386                 :          0 :             index = old->east_asian_width_changed;
         387                 :            :     }
         388                 :          0 :     return PyUnicode_FromString(_PyUnicode_EastAsianWidthNames[index]);
         389                 :            : }
         390                 :            :
         391                 :            : /*[clinic input]
         392                 :            : unicodedata.UCD.decomposition
         393                 :            :
         394                 :            :     self: self
         395                 :            :     chr: int(accept={str})
         396                 :            :     /
         397                 :            :
         398                 :            : Returns the character decomposition mapping assigned to the character chr as string.
         399                 :            :
         400                 :            : An empty string is returned in case no such mapping is defined.
         401                 :            : [clinic start generated code]*/
         402                 :            :
         403                 :            : static PyObject *
         404                 :          0 : unicodedata_UCD_decomposition_impl(PyObject *self, int chr)
         405                 :            : /*[clinic end generated code: output=7d699f3ec7565d27 input=e4c12459ad68507b]*/
         406                 :            : {
         407                 :            :     char decomp[256];
         408                 :            :     int code, index, count;
         409                 :            :     size_t i;
         410                 :            :     unsigned int prefix_index;
         411                 :          0 :     Py_UCS4 c = (Py_UCS4)chr;
         412                 :            :
         413                 :          0 :     code = (int)c;
         414                 :            :
         415   [ #  #  #  # ]:          0 :     if (UCD_Check(self)) {
         416                 :          0 :         const change_record *old = get_old_record(self, c);
         417         [ #  # ]:          0 :         if (old->category_changed == 0)
         418                 :          0 :             return PyUnicode_FromString(""); /* unassigned */
         419                 :            :     }
         420                 :            :
         421   [ #  #  #  # ]:          0 :     if (code < 0 || code >= 0x110000)
         422                 :          0 :         index = 0;
         423                 :            :     else {
         424                 :          0 :         index = decomp_index1[(code>>DECOMP_SHIFT)];
         425                 :          0 :         index = decomp_index2[(index<<DECOMP_SHIFT)+
         426                 :          0 :                              (code&((1<<DECOMP_SHIFT)-1))];
         427                 :            :     }
         428                 :            :
         429                 :            :     /* high byte is number of hex bytes (usually one or two), low byte
         430                 :            :        is prefix code (from*/
         431                 :          0 :     count = decomp_data[index] >> 8;
         432                 :            :
         433                 :            :     /* XXX: could allocate the PyString up front instead
         434                 :            :        (strlen(prefix) + 5 * count + 1 bytes) */
         435                 :            :
         436                 :            :     /* Based on how index is calculated above and decomp_data is generated
         437                 :            :        from Tools/unicode/makeunicodedata.py, it should not be possible
         438                 :            :        to overflow decomp_prefix. */
         439                 :          0 :     prefix_index = decomp_data[index] & 255;
         440                 :            :     assert(prefix_index < Py_ARRAY_LENGTH(decomp_prefix));
         441                 :            :
         442                 :            :     /* copy prefix */
         443                 :          0 :     i = strlen(decomp_prefix[prefix_index]);
         444                 :          0 :     memcpy(decomp, decomp_prefix[prefix_index], i);
         445                 :            :
         446         [ #  # ]:          0 :     while (count-- > 0) {
         447         [ #  # ]:          0 :         if (i)
         448                 :          0 :             decomp[i++] = ' ';
         449                 :            :         assert(i < sizeof(decomp));
         450                 :          0 :         PyOS_snprintf(decomp + i, sizeof(decomp) - i, "%04X",
         451                 :            :                       decomp_data[++index]);
         452                 :          0 :         i += strlen(decomp + i);
         453                 :            :     }
         454                 :          0 :     return PyUnicode_FromStringAndSize(decomp, i);
         455                 :            : }
         456                 :            :
         457                 :            : static void
         458                 :          0 : get_decomp_record(PyObject *self, Py_UCS4 code,
         459                 :            :                   int *index, int *prefix, int *count)
         460                 :            : {
         461         [ #  # ]:          0 :     if (code >= 0x110000) {
         462                 :          0 :         *index = 0;
         463                 :            :     }
         464   [ #  #  #  # ]:          0 :     else if (UCD_Check(self)
         465         [ #  # ]:          0 :              && get_old_record(self, code)->category_changed==0) {
         466                 :            :         /* unassigned in old version */
         467                 :          0 :         *index = 0;
         468                 :            :     }
         469                 :            :     else {
         470                 :          0 :         *index = decomp_index1[(code>>DECOMP_SHIFT)];
         471                 :          0 :         *index = decomp_index2[(*index<<DECOMP_SHIFT)+
         472                 :          0 :                                (code&((1<<DECOMP_SHIFT)-1))];
         473                 :            :     }
         474                 :            :
         475                 :            :     /* high byte is number of hex bytes (usually one or two), low byte
         476                 :            :        is prefix code (from*/
         477                 :          0 :     *count = decomp_data[*index] >> 8;
         478                 :          0 :     *prefix = decomp_data[*index] & 255;
         479                 :            :
         480                 :          0 :     (*index)++;
         481                 :          0 : }
         482                 :            :
         483                 :            : #define SBase   0xAC00
         484                 :            : #define LBase   0x1100
         485                 :            : #define VBase   0x1161
         486                 :            : #define TBase   0x11A7
         487                 :            : #define LCount  19
         488                 :            : #define VCount  21
         489                 :            : #define TCount  28
         490                 :            : #define NCount  (VCount*TCount)
         491                 :            : #define SCount  (LCount*NCount)
         492                 :            :
         493                 :            : static PyObject*
         494                 :          0 : nfd_nfkd(PyObject *self, PyObject *input, int k)
         495                 :            : {
         496                 :            :     PyObject *result;
         497                 :            :     Py_UCS4 *output;
         498                 :            :     Py_ssize_t i, o, osize;
         499                 :            :     int kind;
         500                 :            :     const void *data;
         501                 :            :     /* Longest decomposition in Unicode 3.2: U+FDFA */
         502                 :            :     Py_UCS4 stack[20];
         503                 :            :     Py_ssize_t space, isize;
         504                 :            :     int index, prefix, count, stackptr;
         505                 :            :     unsigned char prev, cur;
         506                 :            :
         507                 :          0 :     stackptr = 0;
         508                 :          0 :     isize = PyUnicode_GET_LENGTH(input);
         509                 :          0 :     space = isize;
         510                 :            :     /* Overallocate at most 10 characters. */
         511         [ #  # ]:          0 :     if (space > 10) {
         512         [ #  # ]:          0 :         if (space <= PY_SSIZE_T_MAX - 10)
         513                 :          0 :             space += 10;
         514                 :            :     }
         515                 :            :     else {
         516                 :          0 :         space *= 2;
         517                 :            :     }
         518                 :          0 :     osize = space;
         519         [ #  # ]:          0 :     output = PyMem_NEW(Py_UCS4, space);
         520         [ #  # ]:          0 :     if (!output) {
         521                 :          0 :         PyErr_NoMemory();
         522                 :          0 :         return NULL;
         523                 :            :     }
         524                 :          0 :     i = o = 0;
         525                 :          0 :     kind = PyUnicode_KIND(input);
         526                 :          0 :     data = PyUnicode_DATA(input);
         527                 :            :
         528         [ #  # ]:          0 :     while (i < isize) {
         529                 :          0 :         stack[stackptr++] = PyUnicode_READ(kind, data, i++);
         530         [ #  # ]:          0 :         while(stackptr) {
         531                 :          0 :             Py_UCS4 code = stack[--stackptr];
         532                 :            :             /* Hangul Decomposition adds three characters in
         533                 :            :                a single step, so we need at least that much room. */
         534         [ #  # ]:          0 :             if (space < 3) {
         535                 :            :                 Py_UCS4 *new_output;
         536                 :          0 :                 osize += 10;
         537                 :          0 :                 space += 10;
         538                 :          0 :                 new_output = PyMem_Realloc(output, osize*sizeof(Py_UCS4));
         539         [ #  # ]:          0 :                 if (new_output == NULL) {
         540                 :          0 :                     PyMem_Free(output);
         541                 :          0 :                     PyErr_NoMemory();
         542                 :          0 :                     return NULL;
         543                 :            :                 }
         544                 :          0 :                 output = new_output;
         545                 :            :             }
         546                 :            :             /* Hangul Decomposition. */
         547   [ #  #  #  # ]:          0 :             if (SBase <= code && code < (SBase+SCount)) {
         548                 :          0 :                 int SIndex = code - SBase;
         549                 :          0 :                 int L = LBase + SIndex / NCount;
         550                 :          0 :                 int V = VBase + (SIndex % NCount) / TCount;
         551                 :          0 :                 int T = TBase + SIndex % TCount;
         552                 :          0 :                 output[o++] = L;
         553                 :          0 :                 output[o++] = V;
         554                 :          0 :                 space -= 2;
         555         [ #  # ]:          0 :                 if (T != TBase) {
         556                 :          0 :                     output[o++] = T;
         557                 :          0 :                     space --;
         558                 :            :                 }
         559                 :          0 :                 continue;
         560                 :            :             }
         561                 :            :             /* normalization changes */
         562   [ #  #  #  # ]:          0 :             if (UCD_Check(self)) {
         563                 :          0 :                 Py_UCS4 value = ((PreviousDBVersion*)self)->normalization(code);
         564         [ #  # ]:          0 :                 if (value != 0) {
         565                 :          0 :                     stack[stackptr++] = value;
         566                 :          0 :                     continue;
         567                 :            :                 }
         568                 :            :             }
         569                 :            :
         570                 :            :             /* Other decompositions. */
         571                 :          0 :             get_decomp_record(self, code, &index, &prefix, &count);
         572                 :            :
         573                 :            :             /* Copy character if it is not decomposable, or has a
         574                 :            :                compatibility decomposition, but we do NFD. */
         575   [ #  #  #  #  :          0 :             if (!count || (prefix && !k)) {
                       #  # ]
         576                 :          0 :                 output[o++] = code;
         577                 :          0 :                 space--;
         578                 :          0 :                 continue;
         579                 :            :             }
         580                 :            :             /* Copy decomposition onto the stack, in reverse
         581                 :            :                order.  */
         582         [ #  # ]:          0 :             while(count) {
         583                 :          0 :                 code = decomp_data[index + (--count)];
         584                 :          0 :                 stack[stackptr++] = code;
         585                 :            :             }
         586                 :            :         }
         587                 :            :     }
         588                 :            :
         589                 :          0 :     result = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND,
         590                 :            :                                        output, o);
         591                 :          0 :     PyMem_Free(output);
         592         [ #  # ]:          0 :     if (!result)
         593                 :          0 :         return NULL;
         594                 :            :     /* result is guaranteed to be ready, as it is compact. */
         595                 :          0 :     kind = PyUnicode_KIND(result);
         596                 :          0 :     data = PyUnicode_DATA(result);
         597                 :            :
         598                 :            :     /* Sort canonically. */
         599                 :          0 :     i = 0;
         600                 :          0 :     prev = _getrecord_ex(PyUnicode_READ(kind, data, i))->combining;
         601         [ #  # ]:          0 :     for (i++; i < PyUnicode_GET_LENGTH(result); i++) {
         602                 :          0 :         cur = _getrecord_ex(PyUnicode_READ(kind, data, i))->combining;
         603   [ #  #  #  #  :          0 :         if (prev == 0 || cur == 0 || prev <= cur) {
                       #  # ]
         604                 :          0 :             prev = cur;
         605                 :          0 :             continue;
         606                 :            :         }
         607                 :            :         /* Non-canonical order. Need to switch *i with previous. */
         608                 :          0 :         o = i - 1;
         609                 :          0 :         while (1) {
         610                 :          0 :             Py_UCS4 tmp = PyUnicode_READ(kind, data, o+1);
         611                 :          0 :             PyUnicode_WRITE(kind, data, o+1,
         612                 :            :                             PyUnicode_READ(kind, data, o));
         613                 :          0 :             PyUnicode_WRITE(kind, data, o, tmp);
         614                 :          0 :             o--;
         615         [ #  # ]:          0 :             if (o < 0)
         616                 :          0 :                 break;
         617                 :          0 :             prev = _getrecord_ex(PyUnicode_READ(kind, data, o))->combining;
         618   [ #  #  #  # ]:          0 :             if (prev == 0 || prev <= cur)
         619                 :            :                 break;
         620                 :            :         }
         621                 :          0 :         prev = _getrecord_ex(PyUnicode_READ(kind, data, i))->combining;
         622                 :            :     }
         623                 :          0 :     return result;
         624                 :            : }
         625                 :            :
         626                 :            : static int
         627                 :          0 : find_nfc_index(const struct reindex* nfc, Py_UCS4 code)
         628                 :            : {
         629                 :            :     unsigned int index;
         630         [ #  # ]:          0 :     for (index = 0; nfc[index].start; index++) {
         631                 :          0 :         unsigned int start = nfc[index].start;
         632         [ #  # ]:          0 :         if (code < start)
         633                 :          0 :             return -1;
         634         [ #  # ]:          0 :         if (code <= start + nfc[index].count) {
         635                 :          0 :             unsigned int delta = code - start;
         636                 :          0 :             return nfc[index].index + delta;
         637                 :            :         }
         638                 :            :     }
         639                 :          0 :     return -1;
         640                 :            : }
         641                 :            :
         642                 :            : static PyObject*
         643                 :          0 : nfc_nfkc(PyObject *self, PyObject *input, int k)
         644                 :            : {
         645                 :            :     PyObject *result;
         646                 :            :     int kind;
         647                 :            :     const void *data;
         648                 :            :     Py_UCS4 *output;
         649                 :            :     Py_ssize_t i, i1, o, len;
         650                 :            :     int f,l,index,index1,comb;
         651                 :            :     Py_UCS4 code;
         652                 :            :     Py_ssize_t skipped[20];
         653                 :          0 :     int cskipped = 0;
         654                 :            :
         655                 :          0 :     result = nfd_nfkd(self, input, k);
         656         [ #  # ]:          0 :     if (!result)
         657                 :          0 :         return NULL;
         658                 :            :     /* result will be "ready". */
         659                 :          0 :     kind = PyUnicode_KIND(result);
         660                 :          0 :     data = PyUnicode_DATA(result);
         661                 :          0 :     len = PyUnicode_GET_LENGTH(result);
         662                 :            :
         663                 :            :     /* We allocate a buffer for the output.
         664                 :            :        If we find that we made no changes, we still return
         665                 :            :        the NFD result. */
         666         [ #  # ]:          0 :     output = PyMem_NEW(Py_UCS4, len);
         667         [ #  # ]:          0 :     if (!output) {
         668                 :          0 :         PyErr_NoMemory();
         669                 :          0 :         Py_DECREF(result);
         670                 :          0 :         return 0;
         671                 :            :     }
         672                 :          0 :     i = o = 0;
         673                 :            :
         674                 :          0 :   again:
         675         [ #  # ]:          0 :     while (i < len) {
         676         [ #  # ]:          0 :       for (index = 0; index < cskipped; index++) {
         677         [ #  # ]:          0 :           if (skipped[index] == i) {
         678                 :            :               /* *i character is skipped.
         679                 :            :                  Remove from list. */
         680                 :          0 :               skipped[index] = skipped[cskipped-1];
         681                 :          0 :               cskipped--;
         682                 :          0 :               i++;
         683                 :          0 :               goto again; /* continue while */
         684                 :            :           }
         685                 :            :       }
         686                 :            :       /* Hangul Composition. We don't need to check for <LV,T>
         687                 :            :          pairs, since we always have decomposed data. */
         688                 :          0 :       code = PyUnicode_READ(kind, data, i);
         689   [ #  #  #  # ]:          0 :       if (LBase <= code && code < (LBase+LCount) &&
         690   [ #  #  #  # ]:          0 :           i + 1 < len &&
         691         [ #  # ]:          0 :           VBase <= PyUnicode_READ(kind, data, i+1) &&
         692                 :          0 :           PyUnicode_READ(kind, data, i+1) < (VBase+VCount)) {
         693                 :            :           /* check L character is a modern leading consonant (0x1100 ~ 0x1112)
         694                 :            :              and V character is a modern vowel (0x1161 ~ 0x1175). */
         695                 :            :           int LIndex, VIndex;
         696                 :          0 :           LIndex = code - LBase;
         697                 :          0 :           VIndex = PyUnicode_READ(kind, data, i+1) - VBase;
         698                 :          0 :           code = SBase + (LIndex*VCount+VIndex)*TCount;
         699                 :          0 :           i+=2;
         700   [ #  #  #  # ]:          0 :           if (i < len &&
         701         [ #  # ]:          0 :               TBase < PyUnicode_READ(kind, data, i) &&
         702                 :          0 :               PyUnicode_READ(kind, data, i) < (TBase+TCount)) {
         703                 :            :               /* check T character is a modern trailing consonant
         704                 :            :                  (0x11A8 ~ 0x11C2). */
         705                 :          0 :               code += PyUnicode_READ(kind, data, i)-TBase;
         706                 :          0 :               i++;
         707                 :            :           }
         708                 :          0 :           output[o++] = code;
         709                 :          0 :           continue;
         710                 :            :       }
         711                 :            :
         712                 :            :       /* code is still input[i] here */
         713                 :          0 :       f = find_nfc_index(nfc_first, code);
         714         [ #  # ]:          0 :       if (f == -1) {
         715                 :          0 :           output[o++] = code;
         716                 :          0 :           i++;
         717                 :          0 :           continue;
         718                 :            :       }
         719                 :            :       /* Find next unblocked character. */
         720                 :          0 :       i1 = i+1;
         721                 :          0 :       comb = 0;
         722                 :            :       /* output base character for now; might be updated later. */
         723                 :          0 :       output[o] = PyUnicode_READ(kind, data, i);
         724         [ #  # ]:          0 :       while (i1 < len) {
         725                 :          0 :           Py_UCS4 code1 = PyUnicode_READ(kind, data, i1);
         726                 :          0 :           int comb1 = _getrecord_ex(code1)->combining;
         727         [ #  # ]:          0 :           if (comb) {
         728         [ #  # ]:          0 :               if (comb1 == 0)
         729                 :          0 :                   break;
         730         [ #  # ]:          0 :               if (comb >= comb1) {
         731                 :            :                   /* Character is blocked. */
         732                 :          0 :                   i1++;
         733                 :          0 :                   continue;
         734                 :            :               }
         735                 :            :           }
         736                 :          0 :           l = find_nfc_index(nfc_last, code1);
         737                 :            :           /* i1 cannot be combined with i. If i1
         738                 :            :              is a starter, we don't need to look further.
         739                 :            :              Otherwise, record the combining class. */
         740         [ #  # ]:          0 :           if (l == -1) {
         741                 :          0 :             not_combinable:
         742         [ #  # ]:          0 :               if (comb1 == 0)
         743                 :          0 :                   break;
         744                 :          0 :               comb = comb1;
         745                 :          0 :               i1++;
         746                 :          0 :               continue;
         747                 :            :           }
         748                 :          0 :           index = f*TOTAL_LAST + l;
         749                 :          0 :           index1 = comp_index[index >> COMP_SHIFT];
         750                 :          0 :           code = comp_data[(index1<<COMP_SHIFT)+
         751                 :          0 :                            (index&((1<<COMP_SHIFT)-1))];
         752         [ #  # ]:          0 :           if (code == 0)
         753                 :          0 :               goto not_combinable;
         754                 :            :
         755                 :            :           /* Replace the original character. */
         756                 :          0 :           output[o] = code;
         757                 :            :           /* Mark the second character unused. */
         758                 :            :           assert(cskipped < 20);
         759                 :          0 :           skipped[cskipped++] = i1;
         760                 :          0 :           i1++;
         761                 :          0 :           f = find_nfc_index(nfc_first, output[o]);
         762         [ #  # ]:          0 :           if (f == -1)
         763                 :          0 :               break;
         764                 :            :       }
         765                 :            :       /* Output character was already written.
         766                 :            :          Just advance the indices. */
         767                 :          0 :       o++; i++;
         768                 :            :     }
         769         [ #  # ]:          0 :     if (o == len) {
         770                 :            :         /* No changes. Return original string. */
         771                 :          0 :         PyMem_Free(output);
         772                 :          0 :         return result;
         773                 :            :     }
         774                 :          0 :     Py_DECREF(result);
         775                 :          0 :     result = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND,
         776                 :            :                                        output, o);
         777                 :          0 :     PyMem_Free(output);
         778                 :          0 :     return result;
         779                 :            : }
         780                 :            :
         781                 :            : // This needs to match the logic in makeunicodedata.py
         782                 :            : // which constructs the quickcheck data.
         783                 :            : typedef enum {YES = 0, MAYBE = 1, NO = 2} QuickcheckResult;
         784                 :            :
         785                 :            : /* Run the Unicode normalization "quickcheck" algorithm.
         786                 :            :  *
         787                 :            :  * Return YES or NO if quickcheck determines the input is certainly
         788                 :            :  * normalized or certainly not, and MAYBE if quickcheck is unable to
         789                 :            :  * tell.
         790                 :            :  *
         791                 :            :  * If `yes_only` is true, then return MAYBE as soon as we determine
         792                 :            :  * the answer is not YES.
         793                 :            :  *
         794                 :            :  * For background and details on the algorithm, see UAX #15:
         795                 :            :  *   https://www.unicode.org/reports/tr15/#Detecting_Normalization_Forms
         796                 :            :  */
         797                 :            : static QuickcheckResult
         798                 :          0 : is_normalized_quickcheck(PyObject *self, PyObject *input, bool nfc, bool k,
         799                 :            :                          bool yes_only)
         800                 :            : {
         801                 :            :     /* UCD 3.2.0 is requested, quickchecks must be disabled. */
         802   [ #  #  #  # ]:          0 :     if (UCD_Check(self)) {
         803                 :          0 :         return MAYBE;
         804                 :            :     }
         805                 :            :
         806         [ #  # ]:          0 :     if (PyUnicode_IS_ASCII(input)) {
         807                 :          0 :         return YES;
         808                 :            :     }
         809                 :            :
         810                 :            :     Py_ssize_t i, len;
         811                 :            :     int kind;
         812                 :            :     const void *data;
         813                 :          0 :     unsigned char prev_combining = 0;
         814                 :            :
         815                 :            :     /* The two quickcheck bits at this shift have type QuickcheckResult. */
         816   [ #  #  #  # ]:          0 :     int quickcheck_shift = (nfc ? 4 : 0) + (k ? 2 : 0);
         817                 :            :
         818                 :          0 :     QuickcheckResult result = YES; /* certainly normalized, unless we find something */
         819                 :            :
         820                 :          0 :     i = 0;
         821                 :          0 :     kind = PyUnicode_KIND(input);
         822                 :          0 :     data = PyUnicode_DATA(input);
         823                 :          0 :     len = PyUnicode_GET_LENGTH(input);
         824         [ #  # ]:          0 :     while (i < len) {
         825                 :          0 :         Py_UCS4 ch = PyUnicode_READ(kind, data, i++);
         826                 :          0 :         const _PyUnicode_DatabaseRecord *record = _getrecord_ex(ch);
         827                 :            :
         828                 :          0 :         unsigned char combining = record->combining;
         829   [ #  #  #  # ]:          0 :         if (combining && prev_combining > combining)
         830                 :          0 :             return NO; /* non-canonical sort order, not normalized */
         831                 :          0 :         prev_combining = combining;
         832                 :            :
         833                 :          0 :         unsigned char quickcheck_whole = record->normalization_quick_check;
         834         [ #  # ]:          0 :         if (yes_only) {
         835         [ #  # ]:          0 :             if (quickcheck_whole & (3 << quickcheck_shift))
         836                 :          0 :                 return MAYBE;
         837                 :            :         } else {
         838      [ #  #  # ]:          0 :             switch ((quickcheck_whole >> quickcheck_shift) & 3) {
         839                 :          0 :             case NO:
         840                 :          0 :               return NO;
         841                 :          0 :             case MAYBE:
         842                 :          0 :               result = MAYBE; /* this string might need normalization */
         843                 :            :             }
         844                 :            :         }
         845                 :            :     }
         846                 :          0 :     return result;
         847                 :            : }
         848                 :            :
         849                 :            : /*[clinic input]
         850                 :            : unicodedata.UCD.is_normalized
         851                 :            :
         852                 :            :     self: self
         853                 :            :     form: unicode
         854                 :            :     unistr as input: unicode
         855                 :            :     /
         856                 :            :
         857                 :            : Return whether the Unicode string unistr is in the normal form 'form'.
         858                 :            :
         859                 :            : Valid values for form are 'NFC', 'NFKC', 'NFD', and 'NFKD'.
         860                 :            : [clinic start generated code]*/
         861                 :            :
         862                 :            : static PyObject *
         863                 :          0 : unicodedata_UCD_is_normalized_impl(PyObject *self, PyObject *form,
         864                 :            :                                    PyObject *input)
         865                 :            : /*[clinic end generated code: output=11e5a3694e723ca5 input=a544f14cea79e508]*/
         866                 :            : {
         867         [ #  # ]:          0 :     if (PyUnicode_READY(input) == -1) {
         868                 :          0 :         return NULL;
         869                 :            :     }
         870                 :            :
         871         [ #  # ]:          0 :     if (PyUnicode_GET_LENGTH(input) == 0) {
         872                 :            :         /* special case empty input strings. */
         873                 :          0 :         Py_RETURN_TRUE;
         874                 :            :     }
         875                 :            :
         876                 :            :     PyObject *result;
         877                 :          0 :     bool nfc = false;
         878                 :          0 :     bool k = false;
         879                 :            :     QuickcheckResult m;
         880                 :            :
         881                 :            :     PyObject *cmp;
         882                 :          0 :     int match = 0;
         883                 :            :
         884         [ #  # ]:          0 :     if (PyUnicode_CompareWithASCIIString(form, "NFC") == 0) {
         885                 :          0 :         nfc = true;
         886                 :            :     }
         887         [ #  # ]:          0 :     else if (PyUnicode_CompareWithASCIIString(form, "NFKC") == 0) {
         888                 :          0 :         nfc = true;
         889                 :          0 :         k = true;
         890                 :            :     }
         891         [ #  # ]:          0 :     else if (PyUnicode_CompareWithASCIIString(form, "NFD") == 0) {
         892                 :            :         /* matches default values for `nfc` and `k` */
         893                 :            :     }
         894         [ #  # ]:          0 :     else if (PyUnicode_CompareWithASCIIString(form, "NFKD") == 0) {
         895                 :          0 :         k = true;
         896                 :            :     }
         897                 :            :     else {
         898                 :          0 :         PyErr_SetString(PyExc_ValueError, "invalid normalization form");
         899                 :          0 :         return NULL;
         900                 :            :     }
         901                 :            :
         902                 :          0 :     m = is_normalized_quickcheck(self, input, nfc, k, false);
         903                 :            :
         904         [ #  # ]:          0 :     if (m == MAYBE) {
         905         [ #  # ]:          0 :         cmp = (nfc ? nfc_nfkc : nfd_nfkd)(self, input, k);
         906         [ #  # ]:          0 :         if (cmp == NULL) {
         907                 :          0 :             return NULL;
         908                 :            :         }
         909                 :          0 :         match = PyUnicode_Compare(input, cmp);
         910                 :          0 :         Py_DECREF(cmp);
         911         [ #  # ]:          0 :         result = (match == 0) ? Py_True : Py_False;
         912                 :            :     }
         913                 :            :     else {
         914         [ #  # ]:          0 :         result = (m == YES) ? Py_True : Py_False;
         915                 :            :     }
         916                 :            :
         917                 :          0 :     return Py_NewRef(result);
         918                 :            : }
         919                 :            :
         920                 :            :
         921                 :            : /*[clinic input]
         922                 :            : unicodedata.UCD.normalize
         923                 :            :
         924                 :            :     self: self
         925                 :            :     form: unicode
         926                 :            :     unistr as input: unicode
         927                 :            :     /
         928                 :            :
         929                 :            : Return the normal form 'form' for the Unicode string unistr.
         930                 :            :
         931                 :            : Valid values for form are 'NFC', 'NFKC', 'NFD', and 'NFKD'.
         932                 :            : [clinic start generated code]*/
         933                 :            :
         934                 :            : static PyObject *
         935                 :          0 : unicodedata_UCD_normalize_impl(PyObject *self, PyObject *form,
         936                 :            :                                PyObject *input)
         937                 :            : /*[clinic end generated code: output=05ca4385a2ad6983 input=3a5206c0ad2833fb]*/
         938                 :            : {
         939         [ #  # ]:          0 :     if (PyUnicode_GET_LENGTH(input) == 0) {
         940                 :            :         /* Special case empty input strings, since resizing
         941                 :            :            them  later would cause internal errors. */
         942                 :          0 :         return Py_NewRef(input);
         943                 :            :     }
         944                 :            :
         945         [ #  # ]:          0 :     if (PyUnicode_CompareWithASCIIString(form, "NFC") == 0) {
         946         [ #  # ]:          0 :         if (is_normalized_quickcheck(self, input,
         947                 :            :                                      true,  false, true) == YES) {
         948                 :          0 :             return Py_NewRef(input);
         949                 :            :         }
         950                 :          0 :         return nfc_nfkc(self, input, 0);
         951                 :            :     }
         952         [ #  # ]:          0 :     if (PyUnicode_CompareWithASCIIString(form, "NFKC") == 0) {
         953         [ #  # ]:          0 :         if (is_normalized_quickcheck(self, input,
         954                 :            :                                      true,  true,  true) == YES) {
         955                 :          0 :             return Py_NewRef(input);
         956                 :            :         }
         957                 :          0 :         return nfc_nfkc(self, input, 1);
         958                 :            :     }
         959         [ #  # ]:          0 :     if (PyUnicode_CompareWithASCIIString(form, "NFD") == 0) {
         960         [ #  # ]:          0 :         if (is_normalized_quickcheck(self, input,
         961                 :            :                                      false, false, true) == YES) {
         962                 :          0 :             return Py_NewRef(input);
         963                 :            :         }
         964                 :          0 :         return nfd_nfkd(self, input, 0);
         965                 :            :     }
         966         [ #  # ]:          0 :     if (PyUnicode_CompareWithASCIIString(form, "NFKD") == 0) {
         967         [ #  # ]:          0 :         if (is_normalized_quickcheck(self, input,
         968                 :            :                                      false, true,  true) == YES) {
         969                 :          0 :             return Py_NewRef(input);
         970                 :            :         }
         971                 :          0 :         return nfd_nfkd(self, input, 1);
         972                 :            :     }
         973                 :          0 :     PyErr_SetString(PyExc_ValueError, "invalid normalization form");
         974                 :          0 :     return NULL;
         975                 :            : }
         976                 :            :
         977                 :            : /* -------------------------------------------------------------------- */
         978                 :            : /* unicode character name tables */
         979                 :            :
         980                 :            : /* data file generated by Tools/unicode/makeunicodedata.py */
         981                 :            : #include "unicodename_db.h"
         982                 :            :
         983                 :            : /* -------------------------------------------------------------------- */
         984                 :            : /* database code (cut and pasted from the unidb package) */
         985                 :            :
         986                 :            : static unsigned long
         987                 :          0 : _gethash(const char *s, int len, int scale)
         988                 :            : {
         989                 :            :     int i;
         990                 :          0 :     unsigned long h = 0;
         991                 :            :     unsigned long ix;
         992         [ #  # ]:          0 :     for (i = 0; i < len; i++) {
         993                 :          0 :         h = (h * scale) + (unsigned char) Py_TOUPPER(s[i]);
         994                 :          0 :         ix = h & 0xff000000;
         995         [ #  # ]:          0 :         if (ix)
         996                 :          0 :             h = (h ^ ((ix>>24) & 0xff)) & 0x00ffffff;
         997                 :            :     }
         998                 :          0 :     return h;
         999                 :            : }
        1000                 :            :
        1001                 :            : static const char * const hangul_syllables[][3] = {
        1002                 :            :     { "G",  "A",   ""   },
        1003                 :            :     { "GG", "AE",  "G"  },
        1004                 :            :     { "N",  "YA",  "GG" },
        1005                 :            :     { "D",  "YAE", "GS" },
        1006                 :            :     { "DD", "EO",  "N", },
        1007                 :            :     { "R",  "E",   "NJ" },
        1008                 :            :     { "M",  "YEO", "NH" },
        1009                 :            :     { "B",  "YE",  "D"  },
        1010                 :            :     { "BB", "O",   "L"  },
        1011                 :            :     { "S",  "WA",  "LG" },
        1012                 :            :     { "SS", "WAE", "LM" },
        1013                 :            :     { "",   "OE",  "LB" },
        1014                 :            :     { "J",  "YO",  "LS" },
        1015                 :            :     { "JJ", "U",   "LT" },
        1016                 :            :     { "C",  "WEO", "LP" },
        1017                 :            :     { "K",  "WE",  "LH" },
        1018                 :            :     { "T",  "WI",  "M"  },
        1019                 :            :     { "P",  "YU",  "B"  },
        1020                 :            :     { "H",  "EU",  "BS" },
        1021                 :            :     { 0,    "YI",  "S"  },
        1022                 :            :     { 0,    "I",   "SS" },
        1023                 :            :     { 0,    0,     "NG" },
        1024                 :            :     { 0,    0,     "J"  },
        1025                 :            :     { 0,    0,     "C"  },
        1026                 :            :     { 0,    0,     "K"  },
        1027                 :            :     { 0,    0,     "T"  },
        1028                 :            :     { 0,    0,     "P"  },
        1029                 :            :     { 0,    0,     "H"  }
        1030                 :            : };
        1031                 :            :
        1032                 :            : /* These ranges need to match makeunicodedata.py:cjk_ranges. */
        1033                 :            : static int
        1034                 :          0 : is_unified_ideograph(Py_UCS4 code)
        1035                 :            : {
        1036                 :            :     return
        1037   [ #  #  #  # ]:          0 :         (0x3400 <= code && code <= 0x4DBF)   || /* CJK Ideograph Extension A */
        1038   [ #  #  #  # ]:          0 :         (0x4E00 <= code && code <= 0x9FFF)   || /* CJK Ideograph */
        1039   [ #  #  #  # ]:          0 :         (0x20000 <= code && code <= 0x2A6DF) || /* CJK Ideograph Extension B */
        1040   [ #  #  #  # ]:          0 :         (0x2A700 <= code && code <= 0x2B739) || /* CJK Ideograph Extension C */
        1041   [ #  #  #  # ]:          0 :         (0x2B740 <= code && code <= 0x2B81D) || /* CJK Ideograph Extension D */
        1042   [ #  #  #  # ]:          0 :         (0x2B820 <= code && code <= 0x2CEA1) || /* CJK Ideograph Extension E */
        1043   [ #  #  #  # ]:          0 :         (0x2CEB0 <= code && code <= 0x2EBE0) || /* CJK Ideograph Extension F */
        1044   [ #  #  #  #  :          0 :         (0x30000 <= code && code <= 0x3134A) || /* CJK Ideograph Extension G */
                       #  # ]
        1045         [ #  # ]:          0 :         (0x31350 <= code && code <= 0x323AF);   /* CJK Ideograph Extension H */
        1046                 :            : }
        1047                 :            :
        1048                 :            : /* macros used to determine if the given code point is in the PUA range that
        1049                 :            :  * we are using to store aliases and named sequences */
        1050                 :            : #define IS_ALIAS(cp) ((cp >= aliases_start) && (cp < aliases_end))
        1051                 :            : #define IS_NAMED_SEQ(cp) ((cp >= named_sequences_start) && \
        1052                 :            :                           (cp < named_sequences_end))
        1053                 :            :
        1054                 :            : static int
        1055                 :          0 : _getucname(PyObject *self,
        1056                 :            :            Py_UCS4 code, char* buffer, int buflen, int with_alias_and_seq)
        1057                 :            : {
        1058                 :            :     /* Find the name associated with the given code point.
        1059                 :            :      * If with_alias_and_seq is 1, check for names in the Private Use Area 15
        1060                 :            :      * that we are using for aliases and named sequences. */
        1061                 :            :     int offset;
        1062                 :            :     int i;
        1063                 :            :     int word;
        1064                 :            :     const unsigned char* w;
        1065                 :            :
        1066         [ #  # ]:          0 :     if (code >= 0x110000)
        1067                 :          0 :         return 0;
        1068                 :            :
        1069                 :            :     /* XXX should we just skip all the code points in the PUAs here? */
        1070   [ #  #  #  #  :          0 :     if (!with_alias_and_seq && (IS_ALIAS(code) || IS_NAMED_SEQ(code)))
              #  #  #  #  #
                          # ]
        1071                 :          0 :         return 0;
        1072                 :            :
        1073   [ #  #  #  # ]:          0 :     if (UCD_Check(self)) {
        1074                 :            :         /* in 3.2.0 there are no aliases and named sequences */
        1075                 :            :         const change_record *old;
        1076   [ #  #  #  #  :          0 :         if (IS_ALIAS(code) || IS_NAMED_SEQ(code))
                 #  #  #  # ]
        1077                 :          0 :             return 0;
        1078                 :          0 :         old = get_old_record(self, code);
        1079         [ #  # ]:          0 :         if (old->category_changed == 0) {
        1080                 :            :             /* unassigned */
        1081                 :          0 :             return 0;
        1082                 :            :         }
        1083                 :            :     }
        1084                 :            :
        1085   [ #  #  #  # ]:          0 :     if (SBase <= code && code < SBase+SCount) {
        1086                 :            :         /* Hangul syllable. */
        1087                 :          0 :         int SIndex = code - SBase;
        1088                 :          0 :         int L = SIndex / NCount;
        1089                 :          0 :         int V = (SIndex % NCount) / TCount;
        1090                 :          0 :         int T = SIndex % TCount;
        1091                 :            :
        1092         [ #  # ]:          0 :         if (buflen < 27)
        1093                 :            :             /* Worst case: HANGUL SYLLABLE <10chars>. */
        1094                 :          0 :             return 0;
        1095                 :          0 :         strcpy(buffer, "HANGUL SYLLABLE ");
        1096                 :          0 :         buffer += 16;
        1097                 :          0 :         strcpy(buffer, hangul_syllables[L][0]);
        1098                 :          0 :         buffer += strlen(hangul_syllables[L][0]);
        1099                 :          0 :         strcpy(buffer, hangul_syllables[V][1]);
        1100                 :          0 :         buffer += strlen(hangul_syllables[V][1]);
        1101                 :          0 :         strcpy(buffer, hangul_syllables[T][2]);
        1102                 :          0 :         buffer += strlen(hangul_syllables[T][2]);
        1103                 :          0 :         *buffer = '\0';
        1104                 :          0 :         return 1;
        1105                 :            :     }
        1106                 :            :
        1107         [ #  # ]:          0 :     if (is_unified_ideograph(code)) {
        1108         [ #  # ]:          0 :         if (buflen < 28)
        1109                 :            :             /* Worst case: CJK UNIFIED IDEOGRAPH-20000 */
        1110                 :          0 :             return 0;
        1111                 :          0 :         sprintf(buffer, "CJK UNIFIED IDEOGRAPH-%X", code);
        1112                 :          0 :         return 1;
        1113                 :            :     }
        1114                 :            :
        1115                 :            :     /* get offset into phrasebook */
        1116                 :          0 :     offset = phrasebook_offset1[(code>>phrasebook_shift)];
        1117                 :          0 :     offset = phrasebook_offset2[(offset<<phrasebook_shift) +
        1118                 :          0 :                                (code&((1<<phrasebook_shift)-1))];
        1119         [ #  # ]:          0 :     if (!offset)
        1120                 :          0 :         return 0;
        1121                 :            :
        1122                 :          0 :     i = 0;
        1123                 :            :
        1124                 :            :     for (;;) {
        1125                 :            :         /* get word index */
        1126                 :          0 :         word = phrasebook[offset] - phrasebook_short;
        1127         [ #  # ]:          0 :         if (word >= 0) {
        1128                 :          0 :             word = (word << 8) + phrasebook[offset+1];
        1129                 :          0 :             offset += 2;
        1130                 :            :         } else
        1131                 :          0 :             word = phrasebook[offset++];
        1132         [ #  # ]:          0 :         if (i) {
        1133         [ #  # ]:          0 :             if (i > buflen)
        1134                 :          0 :                 return 0; /* buffer overflow */
        1135                 :          0 :             buffer[i++] = ' ';
        1136                 :            :         }
        1137                 :            :         /* copy word string from lexicon.  the last character in the
        1138                 :            :            word has bit 7 set.  the last word in a string ends with
        1139                 :            :            0x80 */
        1140                 :          0 :         w = lexicon + lexicon_offset[word];
        1141         [ #  # ]:          0 :         while (*w < 128) {
        1142         [ #  # ]:          0 :             if (i >= buflen)
        1143                 :          0 :                 return 0; /* buffer overflow */
        1144                 :          0 :             buffer[i++] = *w++;
        1145                 :            :         }
        1146         [ #  # ]:          0 :         if (i >= buflen)
        1147                 :          0 :             return 0; /* buffer overflow */
        1148                 :          0 :         buffer[i++] = *w & 127;
        1149         [ #  # ]:          0 :         if (*w == 128)
        1150                 :          0 :             break; /* end of word */
        1151                 :            :     }
        1152                 :            :
        1153                 :          0 :     return 1;
        1154                 :            : }
        1155                 :            :
        1156                 :            : static int
        1157                 :          0 : capi_getucname(Py_UCS4 code,
        1158                 :            :                char* buffer, int buflen,
        1159                 :            :                int with_alias_and_seq)
        1160                 :            : {
        1161                 :          0 :     return _getucname(NULL, code, buffer, buflen, with_alias_and_seq);
        1162                 :            :
        1163                 :            : }
        1164                 :            :
        1165                 :            : static int
        1166                 :          0 : _cmpname(PyObject *self, int code, const char* name, int namelen)
        1167                 :            : {
        1168                 :            :     /* check if code corresponds to the given name */
        1169                 :            :     int i;
        1170                 :            :     char buffer[NAME_MAXLEN+1];
        1171         [ #  # ]:          0 :     if (!_getucname(self, code, buffer, NAME_MAXLEN, 1))
        1172                 :          0 :         return 0;
        1173         [ #  # ]:          0 :     for (i = 0; i < namelen; i++) {
        1174         [ #  # ]:          0 :         if (Py_TOUPPER(name[i]) != buffer[i])
        1175                 :          0 :             return 0;
        1176                 :            :     }
        1177                 :          0 :     return buffer[namelen] == '\0';
        1178                 :            : }
        1179                 :            :
        1180                 :            : static void
        1181                 :          0 : find_syllable(const char *str, int *len, int *pos, int count, int column)
        1182                 :            : {
        1183                 :            :     int i, len1;
        1184                 :          0 :     *len = -1;
        1185         [ #  # ]:          0 :     for (i = 0; i < count; i++) {
        1186                 :          0 :         const char *s = hangul_syllables[i][column];
        1187                 :          0 :         len1 = Py_SAFE_DOWNCAST(strlen(s), size_t, int);
        1188         [ #  # ]:          0 :         if (len1 <= *len)
        1189                 :          0 :             continue;
        1190         [ #  # ]:          0 :         if (strncmp(str, s, len1) == 0) {
        1191                 :          0 :             *len = len1;
        1192                 :          0 :             *pos = i;
        1193                 :            :         }
        1194                 :            :     }
        1195         [ #  # ]:          0 :     if (*len == -1) {
        1196                 :          0 :         *len = 0;
        1197                 :            :     }
        1198                 :          0 : }
        1199                 :            :
        1200                 :            : static int
        1201                 :          0 : _check_alias_and_seq(unsigned int cp, Py_UCS4* code, int with_named_seq)
        1202                 :            : {
        1203                 :            :     /* check if named sequences are allowed */
        1204   [ #  #  #  #  :          0 :     if (!with_named_seq && IS_NAMED_SEQ(cp))
                       #  # ]
        1205                 :          0 :         return 0;
        1206                 :            :     /* if the code point is in the PUA range that we use for aliases,
        1207                 :            :      * convert it to obtain the right code point */
        1208   [ #  #  #  # ]:          0 :     if (IS_ALIAS(cp))
        1209                 :          0 :         *code = name_aliases[cp-aliases_start];
        1210                 :            :     else
        1211                 :          0 :         *code = cp;
        1212                 :          0 :     return 1;
        1213                 :            : }
        1214                 :            :
        1215                 :            : static int
        1216                 :          0 : _getcode(PyObject* self,
        1217                 :            :          const char* name, int namelen, Py_UCS4* code, int with_named_seq)
        1218                 :            : {
        1219                 :            :     /* Return the code point associated with the given name.
        1220                 :            :      * Named aliases are resolved too (unless self != NULL (i.e. we are using
        1221                 :            :      * 3.2.0)).  If with_named_seq is 1, returns the PUA code point that we are
        1222                 :            :      * using for the named sequence, and the caller must then convert it. */
        1223                 :            :     unsigned int h, v;
        1224                 :          0 :     unsigned int mask = code_size-1;
        1225                 :            :     unsigned int i, incr;
        1226                 :            :
        1227                 :            :     /* Check for hangul syllables. */
        1228         [ #  # ]:          0 :     if (strncmp(name, "HANGUL SYLLABLE ", 16) == 0) {
        1229                 :          0 :         int len, L = -1, V = -1, T = -1;
        1230                 :          0 :         const char *pos = name + 16;
        1231                 :          0 :         find_syllable(pos, &len, &L, LCount, 0);
        1232                 :          0 :         pos += len;
        1233                 :          0 :         find_syllable(pos, &len, &V, VCount, 1);
        1234                 :          0 :         pos += len;
        1235                 :          0 :         find_syllable(pos, &len, &T, TCount, 2);
        1236                 :          0 :         pos += len;
        1237   [ #  #  #  #  :          0 :         if (L != -1 && V != -1 && T != -1 && pos-name == namelen) {
                 #  #  #  # ]
        1238                 :          0 :             *code = SBase + (L*VCount+V)*TCount + T;
        1239                 :          0 :             return 1;
        1240                 :            :         }
        1241                 :            :         /* Otherwise, it's an illegal syllable name. */
        1242                 :          0 :         return 0;
        1243                 :            :     }
        1244                 :            :
        1245                 :            :     /* Check for unified ideographs. */
        1246         [ #  # ]:          0 :     if (strncmp(name, "CJK UNIFIED IDEOGRAPH-", 22) == 0) {
        1247                 :            :         /* Four or five hexdigits must follow. */
        1248                 :          0 :         v = 0;
        1249                 :          0 :         name += 22;
        1250                 :          0 :         namelen -= 22;
        1251   [ #  #  #  # ]:          0 :         if (namelen != 4 && namelen != 5)
        1252                 :          0 :             return 0;
        1253         [ #  # ]:          0 :         while (namelen--) {
        1254                 :          0 :             v *= 16;
        1255   [ #  #  #  # ]:          0 :             if (*name >= '0' && *name <= '9')
        1256                 :          0 :                 v += *name - '0';
        1257   [ #  #  #  # ]:          0 :             else if (*name >= 'A' && *name <= 'F')
        1258                 :          0 :                 v += *name - 'A' + 10;
        1259                 :            :             else
        1260                 :          0 :                 return 0;
        1261                 :          0 :             name++;
        1262                 :            :         }
        1263         [ #  # ]:          0 :         if (!is_unified_ideograph(v))
        1264                 :          0 :             return 0;
        1265                 :          0 :         *code = v;
        1266                 :          0 :         return 1;
        1267                 :            :     }
        1268                 :            :
        1269                 :            :     /* the following is the same as python's dictionary lookup, with
        1270                 :            :        only minor changes.  see the makeunicodedata script for more
        1271                 :            :        details */
        1272                 :            :
        1273                 :          0 :     h = (unsigned int) _gethash(name, namelen, code_magic);
        1274                 :          0 :     i = (~h) & mask;
        1275                 :          0 :     v = code_hash[i];
        1276         [ #  # ]:          0 :     if (!v)
        1277                 :          0 :         return 0;
        1278         [ #  # ]:          0 :     if (_cmpname(self, v, name, namelen)) {
        1279                 :          0 :         return _check_alias_and_seq(v, code, with_named_seq);
        1280                 :            :     }
        1281                 :          0 :     incr = (h ^ (h >> 3)) & mask;
        1282         [ #  # ]:          0 :     if (!incr)
        1283                 :          0 :         incr = mask;
        1284                 :            :     for (;;) {
        1285                 :          0 :         i = (i + incr) & mask;
        1286                 :          0 :         v = code_hash[i];
        1287         [ #  # ]:          0 :         if (!v)
        1288                 :          0 :             return 0;
        1289         [ #  # ]:          0 :         if (_cmpname(self, v, name, namelen)) {
        1290                 :          0 :             return _check_alias_and_seq(v, code, with_named_seq);
        1291                 :            :         }
        1292                 :          0 :         incr = incr << 1;
        1293         [ #  # ]:          0 :         if (incr > mask)
        1294                 :          0 :             incr = incr ^ code_poly;
        1295                 :            :     }
        1296                 :            : }
        1297                 :            :
        1298                 :            : static int
        1299                 :          0 : capi_getcode(const char* name, int namelen, Py_UCS4* code,
        1300                 :            :              int with_named_seq)
        1301                 :            : {
        1302                 :          0 :     return _getcode(NULL, name, namelen, code, with_named_seq);
        1303                 :            :
        1304                 :            : }
        1305                 :            :
        1306                 :            : static void
        1307                 :          1 : unicodedata_destroy_capi(PyObject *capsule)
        1308                 :            : {
        1309                 :          1 :     void *capi = PyCapsule_GetPointer(capsule, PyUnicodeData_CAPSULE_NAME);
        1310                 :          1 :     PyMem_Free(capi);
        1311                 :          1 : }
        1312                 :            :
        1313                 :            : static PyObject *
        1314                 :          1 : unicodedata_create_capi(void)
        1315                 :            : {
        1316                 :          1 :     _PyUnicode_Name_CAPI *capi = PyMem_Malloc(sizeof(_PyUnicode_Name_CAPI));
        1317         [ -  + ]:          1 :     if (capi == NULL) {
        1318                 :          0 :         PyErr_NoMemory();
        1319                 :          0 :         return NULL;
        1320                 :            :     }
        1321                 :          1 :     capi->getname = capi_getucname;
        1322                 :          1 :     capi->getcode = capi_getcode;
        1323                 :            :
        1324                 :          1 :     PyObject *capsule = PyCapsule_New(capi,
        1325                 :            :                                       PyUnicodeData_CAPSULE_NAME,
        1326                 :            :                                       unicodedata_destroy_capi);
        1327         [ -  + ]:          1 :     if (capsule == NULL) {
        1328                 :          0 :         PyMem_Free(capi);
        1329                 :            :     }
        1330                 :          1 :     return capsule;
        1331                 :            : };
        1332                 :            :
        1333                 :            :
        1334                 :            : /* -------------------------------------------------------------------- */
        1335                 :            : /* Python bindings */
        1336                 :            :
        1337                 :            : /*[clinic input]
        1338                 :            : unicodedata.UCD.name
        1339                 :            :
        1340                 :            :     self: self
        1341                 :            :     chr: int(accept={str})
        1342                 :            :     default: object=NULL
        1343                 :            :     /
        1344                 :            :
        1345                 :            : Returns the name assigned to the character chr as a string.
        1346                 :            :
        1347                 :            : If no name is defined, default is returned, or, if not given,
        1348                 :            : ValueError is raised.
        1349                 :            : [clinic start generated code]*/
        1350                 :            :
        1351                 :            : static PyObject *
        1352                 :          0 : unicodedata_UCD_name_impl(PyObject *self, int chr, PyObject *default_value)
        1353                 :            : /*[clinic end generated code: output=6bbb37a326407707 input=3e0367f534de56d9]*/
        1354                 :            : {
        1355                 :            :     char name[NAME_MAXLEN+1];
        1356                 :          0 :     Py_UCS4 c = (Py_UCS4)chr;
        1357                 :            :
        1358         [ #  # ]:          0 :     if (!_getucname(self, c, name, NAME_MAXLEN, 0)) {
        1359         [ #  # ]:          0 :         if (default_value == NULL) {
        1360                 :          0 :             PyErr_SetString(PyExc_ValueError, "no such name");
        1361                 :          0 :             return NULL;
        1362                 :            :         }
        1363                 :            :         else {
        1364                 :          0 :             return Py_NewRef(default_value);
        1365                 :            :         }
        1366                 :            :     }
        1367                 :            :
        1368                 :          0 :     return PyUnicode_FromString(name);
        1369                 :            : }
        1370                 :            :
        1371                 :            : /*[clinic input]
        1372                 :            : unicodedata.UCD.lookup
        1373                 :            :
        1374                 :            :     self: self
        1375                 :            :     name: str(accept={str, robuffer}, zeroes=True)
        1376                 :            :     /
        1377                 :            :
        1378                 :            : Look up character by name.
        1379                 :            :
        1380                 :            : If a character with the given name is found, return the
        1381                 :            : corresponding character.  If not found, KeyError is raised.
        1382                 :            : [clinic start generated code]*/
        1383                 :            :
        1384                 :            : static PyObject *
        1385                 :          0 : unicodedata_UCD_lookup_impl(PyObject *self, const char *name,
        1386                 :            :                             Py_ssize_t name_length)
        1387                 :            : /*[clinic end generated code: output=7f03fc4959b242f6 input=a557be0f8607a0d6]*/
        1388                 :            : {
        1389                 :            :     Py_UCS4 code;
        1390                 :            :     unsigned int index;
        1391         [ #  # ]:          0 :     if (name_length > NAME_MAXLEN) {
        1392                 :          0 :         PyErr_SetString(PyExc_KeyError, "name too long");
        1393                 :          0 :         return NULL;
        1394                 :            :     }
        1395                 :            :
        1396         [ #  # ]:          0 :     if (!_getcode(self, name, (int)name_length, &code, 1)) {
        1397                 :          0 :         PyErr_Format(PyExc_KeyError, "undefined character name '%s'", name);
        1398                 :          0 :         return NULL;
        1399                 :            :     }
        1400                 :            :     /* check if code is in the PUA range that we use for named sequences
        1401                 :            :        and convert it */
        1402   [ #  #  #  # ]:          0 :     if (IS_NAMED_SEQ(code)) {
        1403                 :          0 :         index = code-named_sequences_start;
        1404                 :          0 :         return PyUnicode_FromKindAndData(PyUnicode_2BYTE_KIND,
        1405                 :          0 :                                          named_sequences[index].seq,
        1406                 :          0 :                                          named_sequences[index].seqlen);
        1407                 :            :     }
        1408                 :          0 :     return PyUnicode_FromOrdinal(code);
        1409                 :            : }
        1410                 :            :
        1411                 :            : // List of functions used to define module functions *AND* unicodedata.UCD
        1412                 :            : // methods. For module functions, self is the module. For UCD methods, self
        1413                 :            : // is an UCD instance. The UCD_Check() macro is used to check if self is
        1414                 :            : // an UCD instance.
        1415                 :            : static PyMethodDef unicodedata_functions[] = {
        1416                 :            :     UNICODEDATA_UCD_DECIMAL_METHODDEF
        1417                 :            :     UNICODEDATA_UCD_DIGIT_METHODDEF
        1418                 :            :     UNICODEDATA_UCD_NUMERIC_METHODDEF
        1419                 :            :     UNICODEDATA_UCD_CATEGORY_METHODDEF
        1420                 :            :     UNICODEDATA_UCD_BIDIRECTIONAL_METHODDEF
        1421                 :            :     UNICODEDATA_UCD_COMBINING_METHODDEF
        1422                 :            :     UNICODEDATA_UCD_MIRRORED_METHODDEF
        1423                 :            :     UNICODEDATA_UCD_EAST_ASIAN_WIDTH_METHODDEF
        1424                 :            :     UNICODEDATA_UCD_DECOMPOSITION_METHODDEF
        1425                 :            :     UNICODEDATA_UCD_NAME_METHODDEF
        1426                 :            :     UNICODEDATA_UCD_LOOKUP_METHODDEF
        1427                 :            :     UNICODEDATA_UCD_IS_NORMALIZED_METHODDEF
        1428                 :            :     UNICODEDATA_UCD_NORMALIZE_METHODDEF
        1429                 :            :     {NULL, NULL}                /* sentinel */
        1430                 :            : };
        1431                 :            :
        1432                 :            : static int
        1433                 :          6 : ucd_traverse(PreviousDBVersion *self, visitproc visit, void *arg)
        1434                 :            : {
        1435   [ +  -  -  + ]:          6 :     Py_VISIT(Py_TYPE(self));
        1436                 :          6 :     return 0;
        1437                 :            : }
        1438                 :            :
        1439                 :            : static void
        1440                 :          1 : ucd_dealloc(PreviousDBVersion *self)
        1441                 :            : {
        1442                 :          1 :     PyTypeObject *tp = Py_TYPE(self);
        1443                 :          1 :     PyObject_GC_UnTrack(self);
        1444                 :          1 :     PyObject_GC_Del(self);
        1445                 :          1 :     Py_DECREF(tp);
        1446                 :          1 : }
        1447                 :            :
        1448                 :            : static PyType_Slot ucd_type_slots[] = {
        1449                 :            :     {Py_tp_dealloc, ucd_dealloc},
        1450                 :            :     {Py_tp_traverse, ucd_traverse},
        1451                 :            :     {Py_tp_getattro, PyObject_GenericGetAttr},
        1452                 :            :     {Py_tp_methods, unicodedata_functions},
        1453                 :            :     {Py_tp_members, DB_members},
        1454                 :            :     {0, 0}
        1455                 :            : };
        1456                 :            :
        1457                 :            : static PyType_Spec ucd_type_spec = {
        1458                 :            :     .name = "unicodedata.UCD",
        1459                 :            :     .basicsize = sizeof(PreviousDBVersion),
        1460                 :            :     .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION |
        1461                 :            :               Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE),
        1462                 :            :     .slots = ucd_type_slots
        1463                 :            : };
        1464                 :            :
        1465                 :            : PyDoc_STRVAR(unicodedata_docstring,
        1466                 :            : "This module provides access to the Unicode Character Database which\n\
        1467                 :            : defines character properties for all Unicode characters. The data in\n\
        1468                 :            : this database is based on the UnicodeData.txt file version\n\
        1469                 :            : " UNIDATA_VERSION " which is publicly available from ftp://ftp.unicode.org/.\n\
        1470                 :            : \n\
        1471                 :            : The module uses the same names and symbols as defined by the\n\
        1472                 :            : UnicodeData File Format " UNIDATA_VERSION ".");
        1473                 :            :
        1474                 :            : static int
        1475                 :          1 : unicodedata_exec(PyObject *module)
        1476                 :            : {
        1477         [ -  + ]:          1 :     if (PyModule_AddStringConstant(module, "unidata_version", UNIDATA_VERSION) < 0) {
        1478                 :          0 :         return -1;
        1479                 :            :     }
        1480                 :            :
        1481                 :          1 :     PyTypeObject *ucd_type = (PyTypeObject *)PyType_FromSpec(&ucd_type_spec);
        1482         [ -  + ]:          1 :     if (ucd_type == NULL) {
        1483                 :          0 :         return -1;
        1484                 :            :     }
        1485                 :            :
        1486         [ -  + ]:          1 :     if (PyModule_AddType(module, ucd_type) < 0) {
        1487                 :          0 :         Py_DECREF(ucd_type);
        1488                 :          0 :         return -1;
        1489                 :            :     }
        1490                 :            :
        1491                 :            :     // Unicode database version 3.2.0 used by the IDNA encoding
        1492                 :            :     PyObject *v;
        1493                 :          1 :     v = new_previous_version(ucd_type, "3.2.0",
        1494                 :            :                              get_change_3_2_0, normalization_3_2_0);
        1495                 :          1 :     Py_DECREF(ucd_type);
        1496         [ -  + ]:          1 :     if (v == NULL) {
        1497                 :          0 :         return -1;
        1498                 :            :     }
        1499         [ -  + ]:          1 :     if (PyModule_AddObject(module, "ucd_3_2_0", v) < 0) {
        1500                 :          0 :         Py_DECREF(v);
        1501                 :          0 :         return -1;
        1502                 :            :     }
        1503                 :            :
        1504                 :            :     /* Export C API */
        1505                 :          1 :     PyObject *capsule = unicodedata_create_capi();
        1506         [ -  + ]:          1 :     if (capsule == NULL) {
        1507                 :          0 :         return -1;
        1508                 :            :     }
        1509                 :          1 :     int rc = PyModule_AddObjectRef(module, "_ucnhash_CAPI", capsule);
        1510                 :          1 :     Py_DECREF(capsule);
        1511         [ -  + ]:          1 :     if (rc < 0) {
        1512                 :          0 :         return -1;
        1513                 :            :     }
        1514                 :          1 :     return 0;
        1515                 :            : }
        1516                 :            :
        1517                 :            : static PyModuleDef_Slot unicodedata_slots[] = {
        1518                 :            :     {Py_mod_exec, unicodedata_exec},
        1519                 :            :     {0, NULL}
        1520                 :            : };
        1521                 :            :
        1522                 :            : static struct PyModuleDef unicodedata_module = {
        1523                 :            :     PyModuleDef_HEAD_INIT,
        1524                 :            :     .m_name = "unicodedata",
        1525                 :            :     .m_doc = unicodedata_docstring,
        1526                 :            :     .m_size = 0,
        1527                 :            :     .m_methods = unicodedata_functions,
        1528                 :            :     .m_slots = unicodedata_slots,
        1529                 :            : };
        1530                 :            :
        1531                 :            : PyMODINIT_FUNC
        1532                 :          1 : PyInit_unicodedata(void)
        1533                 :            : {
        1534                 :          1 :     return PyModuleDef_Init(&unicodedata_module);
        1535                 :            : }
        1536                 :            :
        1537                 :            :
        1538                 :            : /*
        1539                 :            : Local variables:
        1540                 :            : c-basic-offset: 4
        1541                 :            : indent-tabs-mode: nil
        1542                 :            : End:
        1543                 :            : */

Generated by: LCOV version 1.14