LCOV - code coverage report
Current view: top level - src/backend/utils/adt - pg_locale_builtin.c (source / functions) Hit Total Coverage
Test: PostgreSQL 18devel Lines: 42 44 95.5 %
Date: 2024-12-26 18:15:32 Functions: 5 5 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-----------------------------------------------------------------------
       2             :  *
       3             :  * PostgreSQL locale utilities for builtin provider
       4             :  *
       5             :  * Portions Copyright (c) 2002-2024, PostgreSQL Global Development Group
       6             :  *
       7             :  * src/backend/utils/adt/pg_locale_builtin.c
       8             :  *
       9             :  *-----------------------------------------------------------------------
      10             :  */
      11             : 
      12             : #include "postgres.h"
      13             : 
      14             : #include "catalog/pg_database.h"
      15             : #include "catalog/pg_collation.h"
      16             : #include "common/unicode_case.h"
      17             : #include "common/unicode_category.h"
      18             : #include "mb/pg_wchar.h"
      19             : #include "miscadmin.h"
      20             : #include "utils/builtins.h"
      21             : #include "utils/memutils.h"
      22             : #include "utils/pg_locale.h"
      23             : #include "utils/syscache.h"
      24             : 
      25             : extern pg_locale_t create_pg_locale_builtin(Oid collid,
      26             :                                             MemoryContext context);
      27             : extern size_t strlower_builtin(char *dst, size_t dstsize, const char *src,
      28             :                                ssize_t srclen, pg_locale_t locale);
      29             : extern size_t strtitle_builtin(char *dst, size_t dstsize, const char *src,
      30             :                                ssize_t srclen, pg_locale_t locale);
      31             : extern size_t strupper_builtin(char *dst, size_t dstsize, const char *src,
      32             :                                ssize_t srclen, pg_locale_t locale);
      33             : 
      34             : 
      35             : struct WordBoundaryState
      36             : {
      37             :     const char *str;
      38             :     size_t      len;
      39             :     size_t      offset;
      40             :     bool        init;
      41             :     bool        prev_alnum;
      42             : };
      43             : 
      44             : /*
      45             :  * Simple word boundary iterator that draws boundaries each time the result of
      46             :  * pg_u_isalnum() changes.
      47             :  */
      48             : static size_t
      49         344 : initcap_wbnext(void *state)
      50             : {
      51         344 :     struct WordBoundaryState *wbstate = (struct WordBoundaryState *) state;
      52             : 
      53         752 :     while (wbstate->offset < wbstate->len &&
      54         666 :            wbstate->str[wbstate->offset] != '\0')
      55             :     {
      56         666 :         pg_wchar    u = utf8_to_unicode((unsigned char *) wbstate->str +
      57         666 :                                         wbstate->offset);
      58         666 :         bool        curr_alnum = pg_u_isalnum(u, true);
      59             : 
      60         666 :         if (!wbstate->init || curr_alnum != wbstate->prev_alnum)
      61             :         {
      62         258 :             size_t      prev_offset = wbstate->offset;
      63             : 
      64         258 :             wbstate->init = true;
      65         258 :             wbstate->offset += unicode_utf8len(u);
      66         258 :             wbstate->prev_alnum = curr_alnum;
      67         258 :             return prev_offset;
      68             :         }
      69             : 
      70         408 :         wbstate->offset += unicode_utf8len(u);
      71             :     }
      72             : 
      73          86 :     return wbstate->len;
      74             : }
      75             : 
      76             : size_t
      77       11768 : strlower_builtin(char *dest, size_t destsize, const char *src, ssize_t srclen,
      78             :                  pg_locale_t locale)
      79             : {
      80       11768 :     return unicode_strlower(dest, destsize, src, srclen);
      81             : }
      82             : 
      83             : size_t
      84          86 : strtitle_builtin(char *dest, size_t destsize, const char *src, ssize_t srclen,
      85             :                  pg_locale_t locale)
      86             : {
      87          86 :     struct WordBoundaryState wbstate = {
      88             :         .str = src,
      89             :         .len = srclen,
      90             :         .offset = 0,
      91             :         .init = false,
      92             :         .prev_alnum = false,
      93             :     };
      94             : 
      95          86 :     return unicode_strtitle(dest, destsize, src, srclen,
      96             :                             initcap_wbnext, &wbstate);
      97             : }
      98             : 
      99             : size_t
     100      316786 : strupper_builtin(char *dest, size_t destsize, const char *src, ssize_t srclen,
     101             :                  pg_locale_t locale)
     102             : {
     103      316786 :     return unicode_strupper(dest, destsize, src, srclen);
     104             : }
     105             : 
     106             : pg_locale_t
     107        1728 : create_pg_locale_builtin(Oid collid, MemoryContext context)
     108             : {
     109             :     const char *locstr;
     110             :     pg_locale_t result;
     111             : 
     112        1728 :     if (collid == DEFAULT_COLLATION_OID)
     113             :     {
     114             :         HeapTuple   tp;
     115             :         Datum       datum;
     116             : 
     117        1690 :         tp = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(MyDatabaseId));
     118        1690 :         if (!HeapTupleIsValid(tp))
     119           0 :             elog(ERROR, "cache lookup failed for database %u", MyDatabaseId);
     120        1690 :         datum = SysCacheGetAttrNotNull(DATABASEOID, tp,
     121             :                                        Anum_pg_database_datlocale);
     122        1690 :         locstr = TextDatumGetCString(datum);
     123        1690 :         ReleaseSysCache(tp);
     124             :     }
     125             :     else
     126             :     {
     127             :         HeapTuple   tp;
     128             :         Datum       datum;
     129             : 
     130          38 :         tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
     131          38 :         if (!HeapTupleIsValid(tp))
     132           0 :             elog(ERROR, "cache lookup failed for collation %u", collid);
     133          38 :         datum = SysCacheGetAttrNotNull(COLLOID, tp,
     134             :                                        Anum_pg_collation_colllocale);
     135          38 :         locstr = TextDatumGetCString(datum);
     136          38 :         ReleaseSysCache(tp);
     137             :     }
     138             : 
     139        1728 :     builtin_validate_locale(GetDatabaseEncoding(), locstr);
     140             : 
     141        1728 :     result = MemoryContextAllocZero(context, sizeof(struct pg_locale_struct));
     142             : 
     143        1728 :     result->info.builtin.locale = MemoryContextStrdup(context, locstr);
     144        1728 :     result->provider = COLLPROVIDER_BUILTIN;
     145        1728 :     result->deterministic = true;
     146        1728 :     result->collate_is_c = true;
     147        1728 :     result->ctype_is_c = (strcmp(locstr, "C") == 0);
     148             : 
     149        1728 :     return result;
     150             : }

Generated by: LCOV version 1.14