LCOV - differential code coverage report
Current view: top level - src/common - unicode_case.c (source / functions) Coverage Total Hit UNC UBC GNC CBC DUB DCB
Current: 380a8b2ea024c33a35e7abc8628e7c4f52f9f9f9 vs db5ed03217b9c238703df8b4b286115d6e940488 Lines: 91.7 % 120 110 4 6 21 89 4 21
Current Date: 2026-05-29 21:51:00 -0400 Functions: 84.6 % 13 11 2 11 2 9
Baseline: lcov-20260530-034037-baseline Branches: 74.5 % 102 76 26 2 74 2 4
Baseline Date: 2026-05-29 14:39:03 -0700 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(7,30] days: 100.0 % 6 6 6
(30,360] days: 78.9 % 19 15 4 15
(360..) days: 93.7 % 95 89 6 89
Function coverage date bins:
(7,30] days: 100.0 % 5 5 5
(30,360] days: 66.7 % 6 4 2 4
(360..) days: 100.0 % 2 2 2
Branch coverage date bins:
(7,30] days: 100.0 % 2 2 2
(360..) days: 74.0 % 100 74 26 74

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  * unicode_case.c
                                  3                 :                :  *      Unicode case mapping and case conversion.
                                  4                 :                :  *
                                  5                 :                :  * Portions Copyright (c) 2017-2026, PostgreSQL Global Development Group
                                  6                 :                :  *
                                  7                 :                :  * IDENTIFICATION
                                  8                 :                :  *    src/common/unicode_case.c
                                  9                 :                :  *
                                 10                 :                :  *-------------------------------------------------------------------------
                                 11                 :                :  */
                                 12                 :                : #ifndef FRONTEND
                                 13                 :                : #include "postgres.h"
                                 14                 :                : #else
                                 15                 :                : #include "postgres_fe.h"
                                 16                 :                : #endif
                                 17                 :                : 
                                 18                 :                : #include "common/unicode_case.h"
                                 19                 :                : #include "common/unicode_case_table.h"
                                 20                 :                : #include "common/unicode_category.h"
                                 21                 :                : #include "mb/pg_wchar.h"
                                 22                 :                : 
                                 23                 :                : enum CaseMapResult
                                 24                 :                : {
                                 25                 :                :     CASEMAP_SELF,
                                 26                 :                :     CASEMAP_SIMPLE,
                                 27                 :                :     CASEMAP_SPECIAL,
                                 28                 :                : };
                                 29                 :                : 
                                 30                 :                : /*
                                 31                 :                :  * Map for each case kind.
                                 32                 :                :  */
                                 33                 :                : static const char32_t *const casekind_map[NCaseKind] =
                                 34                 :                : {
                                 35                 :                :     [CaseLower] = case_map_lower,
                                 36                 :                :     [CaseTitle] = case_map_title,
                                 37                 :                :     [CaseUpper] = case_map_upper,
                                 38                 :                :     [CaseFold] = case_map_fold,
                                 39                 :                : };
                                 40                 :                : 
                                 41                 :                : static char32_t find_case_map(char32_t ucs, const char32_t *map);
                                 42                 :                : static size_t convert_case(char *dst, size_t dstsize, const char *src, size_t srclen,
                                 43                 :                :                            CaseKind str_casekind, bool full, WordBoundaryNext wbnext,
                                 44                 :                :                            void *wbstate);
                                 45                 :                : static enum CaseMapResult casemap(char32_t u1, CaseKind casekind, bool full,
                                 46                 :                :                                   const char *src, size_t srclen, size_t srcoff,
                                 47                 :                :                                   char32_t *simple, const char32_t **special);
                                 48                 :                : 
                                 49                 :                : char32_t
  213 jdavis@postgresql.or       50                 :GNC         325 : unicode_lowercase_simple(char32_t code)
                                 51                 :                : {
                                 52                 :            325 :     char32_t    cp = find_case_map(code, case_map_lower);
                                 53                 :                : 
  441 jdavis@postgresql.or       54         [ +  - ]:CBC         325 :     return cp != 0 ? cp : code;
                                 55                 :                : }
                                 56                 :                : 
                                 57                 :                : char32_t
  213 jdavis@postgresql.or       58                 :UNC           0 : unicode_titlecase_simple(char32_t code)
                                 59                 :                : {
                                 60                 :              0 :     char32_t    cp = find_case_map(code, case_map_title);
                                 61                 :                : 
  441 jdavis@postgresql.or       62         [ #  # ]:UBC           0 :     return cp != 0 ? cp : code;
                                 63                 :                : }
                                 64                 :                : 
                                 65                 :                : char32_t
  213 jdavis@postgresql.or       66                 :GNC         325 : unicode_uppercase_simple(char32_t code)
                                 67                 :                : {
                                 68                 :            325 :     char32_t    cp = find_case_map(code, case_map_upper);
                                 69                 :                : 
  441 jdavis@postgresql.or       70         [ +  - ]:CBC         325 :     return cp != 0 ? cp : code;
                                 71                 :                : }
                                 72                 :                : 
                                 73                 :                : char32_t
  213 jdavis@postgresql.or       74                 :UNC           0 : unicode_casefold_simple(char32_t code)
                                 75                 :                : {
                                 76                 :              0 :     char32_t    cp = find_case_map(code, case_map_fold);
                                 77                 :                : 
  441 jdavis@postgresql.or       78         [ #  # ]:UBC           0 :     return cp != 0 ? cp : code;
                                 79                 :                : }
                                 80                 :                : 
                                 81                 :                : /*
                                 82                 :                :  * unicode_strlower()
                                 83                 :                :  *
                                 84                 :                :  * Convert src to lowercase, and return the result length (not including
                                 85                 :                :  * terminating NUL).
                                 86                 :                :  *
                                 87                 :                :  * String src must be encoded in UTF-8.
                                 88                 :                :  *
                                 89                 :                :  * Result string is stored in dst, truncating if larger than dstsize. If
                                 90                 :                :  * dstsize is greater than the result length, dst will be NUL-terminated;
                                 91                 :                :  * otherwise not.
                                 92                 :                :  *
                                 93                 :                :  * If dstsize is zero, dst may be NULL. This is useful for calculating the
                                 94                 :                :  * required buffer size before allocating.
                                 95                 :                :  *
                                 96                 :                :  * If full is true, use special case mappings if available and if the
                                 97                 :                :  * conditions are satisfied.
                                 98                 :                :  */
                                 99                 :                : size_t
   15 jdavis@postgresql.or      100                 :GNC        6312 : unicode_strlower(char *dst, size_t dstsize, const char *src, size_t srclen,
                                101                 :                :                  bool full)
                                102                 :                : {
  498 jdavis@postgresql.or      103                 :CBC        6312 :     return convert_case(dst, dstsize, src, srclen, CaseLower, full, NULL,
                                104                 :                :                         NULL);
                                105                 :                : }
                                106                 :                : 
                                107                 :                : /*
                                108                 :                :  * unicode_strtitle()
                                109                 :                :  *
                                110                 :                :  * Convert src to titlecase, and return the result length (not including
                                111                 :                :  * terminating NUL).
                                112                 :                :  *
                                113                 :                :  * String src must be encoded in UTF-8.
                                114                 :                :  *
                                115                 :                :  * Result string is stored in dst, truncating if larger than dstsize. If
                                116                 :                :  * dstsize is greater than the result length, dst will be NUL-terminated;
                                117                 :                :  * otherwise not.
                                118                 :                :  *
                                119                 :                :  * If dstsize is zero, dst may be NULL. This is useful for calculating the
                                120                 :                :  * required buffer size before allocating.
                                121                 :                :  *
                                122                 :                :  * If full is true, use special case mappings if available and if the
                                123                 :                :  * conditions are satisfied. Otherwise, use only simple mappings and use
                                124                 :                :  * uppercase instead of titlecase.
                                125                 :                :  *
                                126                 :                :  * Titlecasing requires knowledge about word boundaries, which is provided by
                                127                 :                :  * the callback wbnext. A word boundary is the offset of the start of a word
                                128                 :                :  * or the offset of the character immediately following a word.
                                129                 :                :  *
                                130                 :                :  * The caller is expected to initialize and free the callback state
                                131                 :                :  * wbstate. The callback should first return offset 0 for the first boundary;
                                132                 :                :  * then the offset of each subsequent word boundary; then the total length of
                                133                 :                :  * the string to indicate the final boundary.
                                134                 :                :  */
                                135                 :                : size_t
   15 jdavis@postgresql.or      136                 :GNC         133 : unicode_strtitle(char *dst, size_t dstsize, const char *src, size_t srclen,
                                137                 :                :                  bool full, WordBoundaryNext wbnext, void *wbstate)
                                138                 :                : {
  498 jdavis@postgresql.or      139                 :CBC         133 :     return convert_case(dst, dstsize, src, srclen, CaseTitle, full, wbnext,
                                140                 :                :                         wbstate);
                                141                 :                : }
                                142                 :                : 
                                143                 :                : /*
                                144                 :                :  * unicode_strupper()
                                145                 :                :  *
                                146                 :                :  * Convert src to uppercase, and return the result length (not including
                                147                 :                :  * terminating NUL).
                                148                 :                :  *
                                149                 :                :  * String src must be encoded in UTF-8.
                                150                 :                :  *
                                151                 :                :  * Result string is stored in dst, truncating if larger than dstsize. If
                                152                 :                :  * dstsize is greater than the result length, dst will be NUL-terminated;
                                153                 :                :  * otherwise not.
                                154                 :                :  *
                                155                 :                :  * If dstsize is zero, dst may be NULL. This is useful for calculating the
                                156                 :                :  * required buffer size before allocating.
                                157                 :                :  *
                                158                 :                :  * If full is true, use special case mappings if available and if the
                                159                 :                :  * conditions are satisfied.
                                160                 :                :  */
                                161                 :                : size_t
   15 jdavis@postgresql.or      162                 :GNC      158561 : unicode_strupper(char *dst, size_t dstsize, const char *src, size_t srclen,
                                163                 :                :                  bool full)
                                164                 :                : {
  498 jdavis@postgresql.or      165                 :CBC      158561 :     return convert_case(dst, dstsize, src, srclen, CaseUpper, full, NULL,
                                166                 :                :                         NULL);
                                167                 :                : }
                                168                 :                : 
                                169                 :                : /*
                                170                 :                :  * unicode_strfold()
                                171                 :                :  *
                                172                 :                :  * Case fold src, and return the result length (not including terminating
                                173                 :                :  * NUL).
                                174                 :                :  *
                                175                 :                :  * String src must be encoded in UTF-8.
                                176                 :                :  *
                                177                 :                :  * Result string is stored in dst, truncating if larger than dstsize. If
                                178                 :                :  * dstsize is greater than the result length, dst will be NUL-terminated;
                                179                 :                :  * otherwise not.
                                180                 :                :  *
                                181                 :                :  * If dstsize is zero, dst may be NULL. This is useful for calculating the
                                182                 :                :  * required buffer size before allocating.
                                183                 :                :  */
                                184                 :                : size_t
   15 jdavis@postgresql.or      185                 :GNC          10 : unicode_strfold(char *dst, size_t dstsize, const char *src, size_t srclen,
                                186                 :                :                 bool full)
                                187                 :                : {
  492 jdavis@postgresql.or      188                 :CBC          10 :     return convert_case(dst, dstsize, src, srclen, CaseFold, full, NULL,
                                189                 :                :                         NULL);
                                190                 :                : }
                                191                 :                : 
                                192                 :                : /*
                                193                 :                :  * Implement Unicode Default Case Conversion algorithm.
                                194                 :                :  *
                                195                 :                :  * If str_casekind is CaseLower or CaseUpper, map each character in the string
                                196                 :                :  * for which a mapping is available.
                                197                 :                :  *
                                198                 :                :  * If str_casekind is CaseTitle, maps characters found on a word boundary to
                                199                 :                :  * titlecase (or uppercase if full is false) and other characters to
                                200                 :                :  * lowercase. NB: does not currently implement the Unicode behavior in which
                                201                 :                :  * the word boundary is adjusted to the next Cased character. That behavior
                                202                 :                :  * could be implemented as an option, but it doesn't match the default
                                203                 :                :  * behavior of ICU, nor does it match the documented behavior of INITCAP().
                                204                 :                :  *
                                205                 :                :  * If full is true, use special mappings for relevant characters, which can
                                206                 :                :  * map a single codepoint to multiple codepoints, or depend on conditions.
                                207                 :                :  */
                                208                 :                : static size_t
   15 jdavis@postgresql.or      209                 :GNC      165016 : convert_case(char *dst, size_t dstsize, const char *src, size_t srclen,
                                210                 :                :              CaseKind str_casekind, bool full, WordBoundaryNext wbnext,
                                211                 :                :              void *wbstate)
                                212                 :                : {
                                213                 :                :     /* character CaseKind varies while titlecasing */
  792 jdavis@postgresql.or      214                 :CBC      165016 :     CaseKind    chr_casekind = str_casekind;
  814                           215                 :         165016 :     size_t      srcoff = 0;
                                216                 :         165016 :     size_t      result_len = 0;
  792                           217                 :         165016 :     size_t      boundary = 0;
                                218                 :                : 
                                219                 :         165016 :     Assert((str_casekind == CaseTitle && wbnext && wbstate) ||
                                      [ +  +  +  -  
                                     -  +  +  -  +  
                                           -  -  + ]
                                220                 :                :            (str_casekind != CaseTitle && !wbnext && !wbstate));
                                221                 :                : 
                                222         [ +  + ]:         165016 :     if (str_casekind == CaseTitle)
                                223                 :                :     {
                                224                 :            133 :         boundary = wbnext(wbstate);
                                225         [ -  + ]:            133 :         Assert(boundary == 0);  /* start of text is always a boundary */
                                226                 :                :     }
                                227                 :                : 
   15 jdavis@postgresql.or      228         [ +  + ]:GNC      494087 :     while (srcoff < srclen)
                                229                 :                :     {
  124 peter@eisentraut.org      230                 :         329071 :         char32_t    u1 = utf8_to_unicode((const unsigned char *) src + srcoff);
  814 jdavis@postgresql.or      231                 :CBC      329071 :         int         u1len = unicode_utf8len(u1);
  213 jdavis@postgresql.or      232                 :GNC      329071 :         char32_t    simple = 0;
                                233                 :         329071 :         const char32_t *special = NULL;
                                234                 :                :         enum CaseMapResult casemap_result;
                                235                 :                : 
  792 jdavis@postgresql.or      236         [ +  + ]:CBC      329071 :         if (str_casekind == CaseTitle)
                                237                 :                :         {
                                238         [ +  + ]:           1032 :             if (srcoff == boundary)
                                239                 :                :             {
  498                           240         [ +  + ]:            431 :                 chr_casekind = full ? CaseTitle : CaseUpper;
  792                           241                 :            431 :                 boundary = wbnext(wbstate);
                                242                 :                :             }
                                243                 :                :             else
                                244                 :            601 :                 chr_casekind = CaseLower;
                                245                 :                :         }
                                246                 :                : 
  444                           247                 :         329071 :         casemap_result = casemap(u1, chr_casekind, full, src, srclen, srcoff,
                                248                 :                :                                  &simple, &special);
                                249                 :                : 
                                250   [ +  +  +  - ]:         329071 :         switch (casemap_result)
                                251                 :                :         {
                                252                 :             88 :             case CASEMAP_SELF:
                                253                 :                :                 /* no mapping; copy bytes from src */
                                254         [ -  + ]:             88 :                 Assert(simple == 0);
                                255         [ -  + ]:             88 :                 Assert(special == NULL);
                                256         [ +  - ]:             88 :                 if (result_len + u1len <= dstsize)
                                257                 :             88 :                     memcpy(dst + result_len, src + srcoff, u1len);
                                258                 :                : 
                                259                 :             88 :                 result_len += u1len;
                                260                 :             88 :                 break;
                                261                 :         328900 :             case CASEMAP_SIMPLE:
                                262                 :                :                 {
                                263                 :                :                     /* replace with single character */
  213 jdavis@postgresql.or      264                 :GNC      328900 :                     char32_t    u2 = simple;
                                265                 :         328900 :                     char32_t    u2len = unicode_utf8len(u2);
                                266                 :                : 
  444 jdavis@postgresql.or      267         [ -  + ]:CBC      328900 :                     Assert(special == NULL);
                                268         [ +  + ]:         328900 :                     if (result_len + u2len <= dstsize)
                                269                 :         328868 :                         unicode_to_utf8(u2, (unsigned char *) dst + result_len);
                                270                 :                : 
                                271                 :         328900 :                     result_len += u2len;
                                272                 :                :                 }
                                273                 :         328900 :                 break;
                                274                 :             83 :             case CASEMAP_SPECIAL:
                                275                 :                :                 /* replace with up to MAX_CASE_EXPANSION characters */
                                276         [ -  + ]:             83 :                 Assert(simple == 0);
                                277   [ +  -  +  + ]:            205 :                 for (int i = 0; i < MAX_CASE_EXPANSION && special[i]; i++)
                                278                 :                :                 {
  213 jdavis@postgresql.or      279                 :GNC         122 :                     char32_t    u2 = special[i];
  444 jdavis@postgresql.or      280                 :CBC         122 :                     size_t      u2len = unicode_utf8len(u2);
                                281                 :                : 
                                282         [ +  - ]:            122 :                     if (result_len + u2len <= dstsize)
                                283                 :            122 :                         unicode_to_utf8(u2, (unsigned char *) dst + result_len);
                                284                 :                : 
                                285                 :            122 :                     result_len += u2len;
                                286                 :                :                 }
                                287                 :             83 :                 break;
                                288                 :                :         }
                                289                 :                : 
  814                           290                 :         329071 :         srcoff += u1len;
                                291                 :                :     }
                                292                 :                : 
                                293         [ +  + ]:         165016 :     if (result_len < dstsize)
                                294                 :         164968 :         dst[result_len] = '\0';
                                295                 :                : 
                                296                 :         165016 :     return result_len;
                                297                 :                : }
                                298                 :                : 
                                299                 :                : /*
                                300                 :                :  * Check that the condition matches Final_Sigma, described in Unicode Table
                                301                 :                :  * 3-17. The character at the given offset must be directly preceded by a
                                302                 :                :  * Cased character, and must not be directly followed by a Cased character.
                                303                 :                :  *
                                304                 :                :  * Case_Ignorable characters are ignored. NB: some characters may be both
                                305                 :                :  * Cased and Case_Ignorable, in which case they are ignored.
                                306                 :                :  */
                                307                 :                : static bool
  498                           308                 :             50 : check_final_sigma(const unsigned char *str, size_t len, size_t offset)
                                309                 :                : {
                                310                 :                :     /* the start of the string is not preceded by a Cased character */
                                311         [ +  + ]:             50 :     if (offset == 0)
                                312                 :              5 :         return false;
                                313                 :                : 
                                314                 :                :     /* iterate backwards, looking for Cased character */
                                315         [ +  - ]:            120 :     for (int i = offset - 1; i >= 0; i--)
                                316                 :                :     {
                                317   [ +  +  +  + ]:            120 :         if ((str[i] & 0x80) == 0 || (str[i] & 0xC0) == 0xC0)
                                318                 :                :         {
  213 jdavis@postgresql.or      319                 :GNC          65 :             char32_t    curr = utf8_to_unicode(str + i);
                                320                 :                : 
  498 jdavis@postgresql.or      321         [ +  + ]:CBC          65 :             if (pg_u_prop_case_ignorable(curr))
                                322                 :             20 :                 continue;
                                323         [ +  + ]:             45 :             else if (pg_u_prop_cased(curr))
                                324                 :             35 :                 break;
                                325                 :                :             else
                                326                 :             10 :                 return false;
                                327                 :                :         }
                                328         [ +  - ]:             55 :         else if ((str[i] & 0xC0) == 0x80)
                                329                 :             55 :             continue;
                                330                 :                : 
  498 jdavis@postgresql.or      331                 :UBC           0 :         Assert(false);          /* invalid UTF-8 */
                                332                 :                :     }
                                333                 :                : 
                                334                 :                :     /* end of string is not followed by a Cased character */
  498 jdavis@postgresql.or      335         [ -  + ]:CBC          35 :     if (offset == len)
  498 jdavis@postgresql.or      336                 :UBC           0 :         return true;
                                337                 :                : 
                                338                 :                :     /* iterate forwards, looking for Cased character */
  498 jdavis@postgresql.or      339   [ +  +  +  - ]:CBC         110 :     for (int i = offset + 1; i < len && str[i] != '\0'; i++)
                                340                 :                :     {
                                341   [ +  +  +  + ]:             95 :         if ((str[i] & 0x80) == 0 || (str[i] & 0xC0) == 0xC0)
                                342                 :                :         {
  213 jdavis@postgresql.or      343                 :GNC          40 :             char32_t    curr = utf8_to_unicode(str + i);
                                344                 :                : 
  498 jdavis@postgresql.or      345         [ +  + ]:CBC          40 :             if (pg_u_prop_case_ignorable(curr))
                                346                 :             20 :                 continue;
                                347         [ +  + ]:             20 :             else if (pg_u_prop_cased(curr))
                                348                 :             15 :                 return false;
                                349                 :                :             else
                                350                 :              5 :                 break;
                                351                 :                :         }
                                352         [ +  - ]:             55 :         else if ((str[i] & 0xC0) == 0x80)
                                353                 :             55 :             continue;
                                354                 :                : 
  498 jdavis@postgresql.or      355                 :UBC           0 :         Assert(false);          /* invalid UTF-8 */
                                356                 :                :     }
                                357                 :                : 
  498 jdavis@postgresql.or      358                 :CBC          20 :     return true;
                                359                 :                : }
                                360                 :                : 
                                361                 :                : /*
                                362                 :                :  * Unicode allows for special casing to be applied only under certain
                                363                 :                :  * circumstances. The only currently-supported condition is Final_Sigma.
                                364                 :                :  */
                                365                 :                : static bool
                                366                 :            113 : check_special_conditions(int conditions, const char *str, size_t len,
                                367                 :                :                          size_t offset)
                                368                 :                : {
                                369         [ +  + ]:            113 :     if (conditions == 0)
                                370                 :             63 :         return true;
                                371         [ +  - ]:             50 :     else if (conditions == PG_U_FINAL_SIGMA)
  124 peter@eisentraut.org      372                 :GNC          50 :         return check_final_sigma((const unsigned char *) str, len, offset);
                                373                 :                : 
                                374                 :                :     /* no other conditions supported */
  498 jdavis@postgresql.or      375                 :UBC           0 :     Assert(false);
                                376                 :                :     return false;
                                377                 :                : }
                                378                 :                : 
                                379                 :                : /*
                                380                 :                :  * Map the given character to the requested case.
                                381                 :                :  *
                                382                 :                :  * If full is true, and a special case mapping is found and the conditions are
                                383                 :                :  * met, 'special' is set to the mapping result (which is an array of up to
                                384                 :                :  * MAX_CASE_EXPANSION characters) and CASEMAP_SPECIAL is returned.
                                385                 :                :  *
                                386                 :                :  * Otherwise, search for a simple mapping, and if found, set 'simple' to the
                                387                 :                :  * result and return CASEMAP_SIMPLE.
                                388                 :                :  *
                                389                 :                :  * If no mapping is found, return CASEMAP_SELF, and the caller should copy the
                                390                 :                :  * character without modification.
                                391                 :                :  */
                                392                 :                : static enum CaseMapResult
  213 jdavis@postgresql.or      393                 :GNC      329071 : casemap(char32_t u1, CaseKind casekind, bool full,
                                394                 :                :         const char *src, size_t srclen, size_t srcoff,
                                395                 :                :         char32_t *simple, const char32_t **special)
                                396                 :                : {
                                397                 :                :     uint16      idx;
                                398                 :                : 
                                399                 :                :     /* Fast path for codepoints < 0x80 */
  444 jdavis@postgresql.or      400         [ +  + ]:CBC      329071 :     if (u1 < 0x80)
                                401                 :                :     {
                                402                 :                :         /*
                                403                 :                :          * The first elements in all tables are reserved as 0 (as NULL). The
                                404                 :                :          * data starts at index 1, not 0.
                                405                 :                :          */
  441                           406                 :         327650 :         *simple = casekind_map[casekind][u1 + 1];
                                407                 :                : 
  444                           408                 :         327650 :         return CASEMAP_SIMPLE;
                                409                 :                :     }
                                410                 :                : 
  441                           411                 :           1421 :     idx = case_index(u1);
                                412                 :                : 
                                413         [ +  + ]:           1421 :     if (idx == 0)
  444                           414                 :             88 :         return CASEMAP_SELF;
                                415                 :                : 
  441                           416   [ +  +  +  +  :           1446 :     if (full && case_map_special[idx] &&
                                              +  + ]
                                417                 :            113 :         check_special_conditions(special_case[case_map_special[idx]].conditions,
                                418                 :                :                                  src, srclen, srcoff))
                                419                 :                :     {
                                420                 :             83 :         *special = special_case[case_map_special[idx]].map[casekind];
  444                           421                 :             83 :         return CASEMAP_SPECIAL;
                                422                 :                :     }
                                423                 :                : 
  441                           424                 :           1250 :     *simple = casekind_map[casekind][idx];
                                425                 :                : 
  444                           426                 :           1250 :     return CASEMAP_SIMPLE;
                                427                 :                : }
                                428                 :                : 
                                429                 :                : /*
                                430                 :                :  * Find entry in simple case map.
                                431                 :                :  * If the entry does not exist, 0 will be returned.
                                432                 :                :  */
                                433                 :                : static char32_t
  213 jdavis@postgresql.or      434                 :GNC         650 : find_case_map(char32_t ucs, const char32_t *map)
                                435                 :                : {
                                436                 :                :     /* Fast path for codepoints < 0x80 */
  814 jdavis@postgresql.or      437         [ +  + ]:CBC         650 :     if (ucs < 0x80)
                                438                 :                :         /* The first elements in all tables are reserved as 0 (as NULL). */
  441                           439                 :            362 :         return map[ucs + 1];
                                440                 :            288 :     return map[case_index(ucs)];
                                441                 :                : }
        

Generated by: LCOV version 2.5.0-beta