LCOV - differential code coverage report
Current view: top level - src/backend/utils/adt - oracle_compat.c (source / functions) Coverage Total Hit LBC UIC UBC GIC CBC EUB ECB
Current: Differential Code Coverage HEAD vs 15 Lines: 84.8 % 396 336 12 25 23 184 152 37 172
Current Date: 2023-04-08 15:15:32 Functions: 100.0 % 20 20 20 20
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /*-------------------------------------------------------------------------
       2                 :  * oracle_compat.c
       3                 :  *  Oracle compatible functions.
       4                 :  *
       5                 :  * Copyright (c) 1996-2023, PostgreSQL Global Development Group
       6                 :  *
       7                 :  *  Author: Edmund Mergl <E.Mergl@bawue.de>
       8                 :  *  Multibyte enhancement: Tatsuo Ishii <ishii@postgresql.org>
       9                 :  *
      10                 :  *
      11                 :  * IDENTIFICATION
      12                 :  *  src/backend/utils/adt/oracle_compat.c
      13                 :  *
      14                 :  *-------------------------------------------------------------------------
      15                 :  */
      16                 : #include "postgres.h"
      17                 : 
      18                 : #include "common/int.h"
      19                 : #include "mb/pg_wchar.h"
      20                 : #include "miscadmin.h"
      21                 : #include "utils/builtins.h"
      22                 : #include "utils/formatting.h"
      23                 : #include "utils/memutils.h"
      24                 : #include "varatt.h"
      25                 : 
      26                 : 
      27                 : static text *dotrim(const char *string, int stringlen,
      28                 :                     const char *set, int setlen,
      29                 :                     bool doltrim, bool dortrim);
      30                 : static bytea *dobyteatrim(bytea *string, bytea *set,
      31                 :                           bool doltrim, bool dortrim);
      32                 : 
      33                 : 
      34                 : /********************************************************************
      35                 :  *
      36                 :  * lower
      37                 :  *
      38                 :  * Syntax:
      39                 :  *
      40                 :  *   text lower(text string)
      41                 :  *
      42                 :  * Purpose:
      43                 :  *
      44                 :  *   Returns string, with all letters forced to lowercase.
      45                 :  *
      46                 :  ********************************************************************/
      47                 : 
      48                 : Datum
      49 GIC       97762 : lower(PG_FUNCTION_ARGS)
      50 ECB             : {
      51 GIC       97762 :     text       *in_string = PG_GETARG_TEXT_PP(0);
      52 ECB             :     char       *out_string;
      53                 :     text       *result;
      54                 : 
      55 GIC       97762 :     out_string = str_tolower(VARDATA_ANY(in_string),
      56 CBC       97762 :                              VARSIZE_ANY_EXHDR(in_string),
      57 ECB             :                              PG_GET_COLLATION());
      58 GIC       97762 :     result = cstring_to_text(out_string);
      59 CBC       97762 :     pfree(out_string);
      60 ECB             : 
      61 GIC       97762 :     PG_RETURN_TEXT_P(result);
      62 ECB             : }
      63                 : 
      64                 : 
      65                 : /********************************************************************
      66                 :  *
      67                 :  * upper
      68                 :  *
      69                 :  * Syntax:
      70                 :  *
      71                 :  *   text upper(text string)
      72                 :  *
      73                 :  * Purpose:
      74                 :  *
      75                 :  *   Returns string, with all letters forced to uppercase.
      76                 :  *
      77                 :  ********************************************************************/
      78                 : 
      79                 : Datum
      80 GIC      521129 : upper(PG_FUNCTION_ARGS)
      81 ECB             : {
      82 GIC      521129 :     text       *in_string = PG_GETARG_TEXT_PP(0);
      83 ECB             :     char       *out_string;
      84                 :     text       *result;
      85                 : 
      86 GIC      521129 :     out_string = str_toupper(VARDATA_ANY(in_string),
      87 CBC      521129 :                              VARSIZE_ANY_EXHDR(in_string),
      88 ECB             :                              PG_GET_COLLATION());
      89 GIC      521129 :     result = cstring_to_text(out_string);
      90 CBC      521129 :     pfree(out_string);
      91 ECB             : 
      92 GIC      521129 :     PG_RETURN_TEXT_P(result);
      93 ECB             : }
      94                 : 
      95                 : 
      96                 : /********************************************************************
      97                 :  *
      98                 :  * initcap
      99                 :  *
     100                 :  * Syntax:
     101                 :  *
     102                 :  *   text initcap(text string)
     103                 :  *
     104                 :  * Purpose:
     105                 :  *
     106                 :  *   Returns string, with first letter of each word in uppercase, all
     107                 :  *   other letters in lowercase. A word is defined as a sequence of
     108                 :  *   alphanumeric characters, delimited by non-alphanumeric
     109                 :  *   characters.
     110                 :  *
     111                 :  ********************************************************************/
     112                 : 
     113                 : Datum
     114 GIC          41 : initcap(PG_FUNCTION_ARGS)
     115 ECB             : {
     116 GIC          41 :     text       *in_string = PG_GETARG_TEXT_PP(0);
     117 ECB             :     char       *out_string;
     118                 :     text       *result;
     119                 : 
     120 GIC          41 :     out_string = str_initcap(VARDATA_ANY(in_string),
     121 CBC          41 :                              VARSIZE_ANY_EXHDR(in_string),
     122 ECB             :                              PG_GET_COLLATION());
     123 GIC          41 :     result = cstring_to_text(out_string);
     124 CBC          41 :     pfree(out_string);
     125 ECB             : 
     126 GIC          41 :     PG_RETURN_TEXT_P(result);
     127 ECB             : }
     128                 : 
     129                 : 
     130                 : /********************************************************************
     131                 :  *
     132                 :  * lpad
     133                 :  *
     134                 :  * Syntax:
     135                 :  *
     136                 :  *   text lpad(text string1, int4 len, text string2)
     137                 :  *
     138                 :  * Purpose:
     139                 :  *
     140                 :  *   Returns string1, left-padded to length len with the sequence of
     141                 :  *   characters in string2.  If len is less than the length of string1,
     142                 :  *   instead truncate (on the right) to len.
     143                 :  *
     144                 :  ********************************************************************/
     145                 : 
     146                 : Datum
     147 GIC       16385 : lpad(PG_FUNCTION_ARGS)
     148 ECB             : {
     149 GIC       16385 :     text       *string1 = PG_GETARG_TEXT_PP(0);
     150 CBC       16385 :     int32       len = PG_GETARG_INT32(1);
     151           16385 :     text       *string2 = PG_GETARG_TEXT_PP(2);
     152 ECB             :     text       *ret;
     153                 :     char       *ptr1,
     154                 :                *ptr2,
     155                 :                *ptr2start,
     156                 :                *ptr2end,
     157                 :                *ptr_ret;
     158                 :     int         m,
     159                 :                 s1len,
     160                 :                 s2len;
     161                 :     int         bytelen;
     162                 : 
     163                 :     /* Negative len is silently taken as zero */
     164 GIC       16385 :     if (len < 0)
     165 CBC           3 :         len = 0;
     166 ECB             : 
     167 GIC       16385 :     s1len = VARSIZE_ANY_EXHDR(string1);
     168 CBC       16385 :     if (s1len < 0)
     169 LBC           0 :         s1len = 0;              /* shouldn't happen */
     170 EUB             : 
     171 GIC       16385 :     s2len = VARSIZE_ANY_EXHDR(string2);
     172 CBC       16385 :     if (s2len < 0)
     173 LBC           0 :         s2len = 0;              /* shouldn't happen */
     174 EUB             : 
     175 GIC       16385 :     s1len = pg_mbstrlen_with_len(VARDATA_ANY(string1), s1len);
     176 ECB             : 
     177 GIC       16385 :     if (s1len > len)
     178 CBC          35 :         s1len = len;            /* truncate string1 to len chars */
     179 ECB             : 
     180 GIC       16385 :     if (s2len <= 0)
     181 CBC           3 :         len = s1len;            /* nothing to pad with, so don't pad */
     182 ECB             : 
     183                 :     /* compute worst-case output length */
     184 GIC       16385 :     if (unlikely(pg_mul_s32_overflow(pg_database_encoding_max_length(), len,
     185 CBC       16385 :                                      &bytelen)) ||
     186           16385 :         unlikely(pg_add_s32_overflow(bytelen, VARHDRSZ, &bytelen)) ||
     187           16385 :         unlikely(!AllocSizeIsValid(bytelen)))
     188 LBC           0 :         ereport(ERROR,
     189 EUB             :                 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
     190                 :                  errmsg("requested length too large")));
     191                 : 
     192 GIC       16385 :     ret = (text *) palloc(bytelen);
     193 ECB             : 
     194 GIC       16385 :     m = len - s1len;
     195 ECB             : 
     196 GIC       16385 :     ptr2 = ptr2start = VARDATA_ANY(string2);
     197 CBC       16385 :     ptr2end = ptr2 + s2len;
     198           16385 :     ptr_ret = VARDATA(ret);
     199 ECB             : 
     200 GIC       17443 :     while (m--)
     201 ECB             :     {
     202 GIC        1058 :         int         mlen = pg_mblen(ptr2);
     203 ECB             : 
     204 GIC        1058 :         memcpy(ptr_ret, ptr2, mlen);
     205 CBC        1058 :         ptr_ret += mlen;
     206            1058 :         ptr2 += mlen;
     207            1058 :         if (ptr2 == ptr2end)    /* wrap around at end of s2 */
     208            1046 :             ptr2 = ptr2start;
     209 ECB             :     }
     210                 : 
     211 GIC       16385 :     ptr1 = VARDATA_ANY(string1);
     212 ECB             : 
     213 GIC       48121 :     while (s1len--)
     214 ECB             :     {
     215 GIC       31736 :         int         mlen = pg_mblen(ptr1);
     216 ECB             : 
     217 GIC       31736 :         memcpy(ptr_ret, ptr1, mlen);
     218 CBC       31736 :         ptr_ret += mlen;
     219           31736 :         ptr1 += mlen;
     220 ECB             :     }
     221                 : 
     222 GIC       16385 :     SET_VARSIZE(ret, ptr_ret - (char *) ret);
     223 ECB             : 
     224 GIC       16385 :     PG_RETURN_TEXT_P(ret);
     225 ECB             : }
     226                 : 
     227                 : 
     228                 : /********************************************************************
     229                 :  *
     230                 :  * rpad
     231                 :  *
     232                 :  * Syntax:
     233                 :  *
     234                 :  *   text rpad(text string1, int4 len, text string2)
     235                 :  *
     236                 :  * Purpose:
     237                 :  *
     238                 :  *   Returns string1, right-padded to length len with the sequence of
     239                 :  *   characters in string2.  If len is less than the length of string1,
     240                 :  *   instead truncate (on the right) to len.
     241                 :  *
     242                 :  ********************************************************************/
     243                 : 
     244                 : Datum
     245 GIC          22 : rpad(PG_FUNCTION_ARGS)
     246 ECB             : {
     247 GIC          22 :     text       *string1 = PG_GETARG_TEXT_PP(0);
     248 CBC          22 :     int32       len = PG_GETARG_INT32(1);
     249              22 :     text       *string2 = PG_GETARG_TEXT_PP(2);
     250 ECB             :     text       *ret;
     251                 :     char       *ptr1,
     252                 :                *ptr2,
     253                 :                *ptr2start,
     254                 :                *ptr2end,
     255                 :                *ptr_ret;
     256                 :     int         m,
     257                 :                 s1len,
     258                 :                 s2len;
     259                 :     int         bytelen;
     260                 : 
     261                 :     /* Negative len is silently taken as zero */
     262 GIC          22 :     if (len < 0)
     263 CBC           3 :         len = 0;
     264 ECB             : 
     265 GIC          22 :     s1len = VARSIZE_ANY_EXHDR(string1);
     266 CBC          22 :     if (s1len < 0)
     267 LBC           0 :         s1len = 0;              /* shouldn't happen */
     268 EUB             : 
     269 GIC          22 :     s2len = VARSIZE_ANY_EXHDR(string2);
     270 CBC          22 :     if (s2len < 0)
     271 LBC           0 :         s2len = 0;              /* shouldn't happen */
     272 EUB             : 
     273 GIC          22 :     s1len = pg_mbstrlen_with_len(VARDATA_ANY(string1), s1len);
     274 ECB             : 
     275 GIC          22 :     if (s1len > len)
     276 CBC           6 :         s1len = len;            /* truncate string1 to len chars */
     277 ECB             : 
     278 GIC          22 :     if (s2len <= 0)
     279 CBC           3 :         len = s1len;            /* nothing to pad with, so don't pad */
     280 ECB             : 
     281                 :     /* compute worst-case output length */
     282 GIC          22 :     if (unlikely(pg_mul_s32_overflow(pg_database_encoding_max_length(), len,
     283 CBC          22 :                                      &bytelen)) ||
     284              22 :         unlikely(pg_add_s32_overflow(bytelen, VARHDRSZ, &bytelen)) ||
     285              22 :         unlikely(!AllocSizeIsValid(bytelen)))
     286 LBC           0 :         ereport(ERROR,
     287 EUB             :                 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
     288                 :                  errmsg("requested length too large")));
     289                 : 
     290 GIC          22 :     ret = (text *) palloc(bytelen);
     291 ECB             : 
     292 GIC          22 :     m = len - s1len;
     293 ECB             : 
     294 GIC          22 :     ptr1 = VARDATA_ANY(string1);
     295 CBC          22 :     ptr_ret = VARDATA(ret);
     296 ECB             : 
     297 GIC          54 :     while (s1len--)
     298 ECB             :     {
     299 GIC          32 :         int         mlen = pg_mblen(ptr1);
     300 ECB             : 
     301 GIC          32 :         memcpy(ptr_ret, ptr1, mlen);
     302 CBC          32 :         ptr_ret += mlen;
     303              32 :         ptr1 += mlen;
     304 ECB             :     }
     305                 : 
     306 GIC          22 :     ptr2 = ptr2start = VARDATA_ANY(string2);
     307 CBC          22 :     ptr2end = ptr2 + s2len;
     308 ECB             : 
     309 GIC      960052 :     while (m--)
     310 ECB             :     {
     311 GIC      960030 :         int         mlen = pg_mblen(ptr2);
     312 ECB             : 
     313 GIC      960030 :         memcpy(ptr_ret, ptr2, mlen);
     314 CBC      960030 :         ptr_ret += mlen;
     315          960030 :         ptr2 += mlen;
     316          960030 :         if (ptr2 == ptr2end)    /* wrap around at end of s2 */
     317          960018 :             ptr2 = ptr2start;
     318 ECB             :     }
     319                 : 
     320 GIC          22 :     SET_VARSIZE(ret, ptr_ret - (char *) ret);
     321 ECB             : 
     322 GIC          22 :     PG_RETURN_TEXT_P(ret);
     323 ECB             : }
     324                 : 
     325                 : 
     326                 : /********************************************************************
     327                 :  *
     328                 :  * btrim
     329                 :  *
     330                 :  * Syntax:
     331                 :  *
     332                 :  *   text btrim(text string, text set)
     333                 :  *
     334                 :  * Purpose:
     335                 :  *
     336                 :  *   Returns string with characters removed from the front and back
     337                 :  *   up to the first character not in set.
     338                 :  *
     339                 :  ********************************************************************/
     340                 : 
     341                 : Datum
     342 GIC          10 : btrim(PG_FUNCTION_ARGS)
     343 ECB             : {
     344 GIC          10 :     text       *string = PG_GETARG_TEXT_PP(0);
     345 CBC          10 :     text       *set = PG_GETARG_TEXT_PP(1);
     346 ECB             :     text       *ret;
     347                 : 
     348 GIC          20 :     ret = dotrim(VARDATA_ANY(string), VARSIZE_ANY_EXHDR(string),
     349 CBC          20 :                  VARDATA_ANY(set), VARSIZE_ANY_EXHDR(set),
     350 ECB             :                  true, true);
     351                 : 
     352 GIC          10 :     PG_RETURN_TEXT_P(ret);
     353 ECB             : }
     354                 : 
     355                 : /********************************************************************
     356                 :  *
     357                 :  * btrim1 --- btrim with set fixed as ' '
     358                 :  *
     359                 :  ********************************************************************/
     360                 : 
     361                 : Datum
     362 GIC         281 : btrim1(PG_FUNCTION_ARGS)
     363 ECB             : {
     364 GIC         281 :     text       *string = PG_GETARG_TEXT_PP(0);
     365 ECB             :     text       *ret;
     366                 : 
     367 GIC         281 :     ret = dotrim(VARDATA_ANY(string), VARSIZE_ANY_EXHDR(string),
     368 ECB             :                  " ", 1,
     369                 :                  true, true);
     370                 : 
     371 GIC         281 :     PG_RETURN_TEXT_P(ret);
     372 ECB             : }
     373                 : 
     374                 : /*
     375                 :  * Common implementation for btrim, ltrim, rtrim
     376                 :  */
     377                 : static text *
     378 GIC       17397 : dotrim(const char *string, int stringlen,
     379 ECB             :        const char *set, int setlen,
     380                 :        bool doltrim, bool dortrim)
     381                 : {
     382                 :     int         i;
     383                 : 
     384                 :     /* Nothing to do if either string or set is empty */
     385 GIC       17397 :     if (stringlen > 0 && setlen > 0)
     386 ECB             :     {
     387 GIC       17397 :         if (pg_database_encoding_max_length() > 1)
     388 ECB             :         {
     389                 :             /*
     390                 :              * In the multibyte-encoding case, build arrays of pointers to
     391                 :              * character starts, so that we can avoid inefficient checks in
     392                 :              * the inner loops.
     393                 :              */
     394                 :             const char **stringchars;
     395                 :             const char **setchars;
     396                 :             int        *stringmblen;
     397                 :             int        *setmblen;
     398                 :             int         stringnchars;
     399                 :             int         setnchars;
     400                 :             int         resultndx;
     401                 :             int         resultnchars;
     402                 :             const char *p;
     403                 :             int         len;
     404                 :             int         mblen;
     405                 :             const char *str_pos;
     406                 :             int         str_len;
     407                 : 
     408 GIC       17391 :             stringchars = (const char **) palloc(stringlen * sizeof(char *));
     409 CBC       17391 :             stringmblen = (int *) palloc(stringlen * sizeof(int));
     410           17391 :             stringnchars = 0;
     411           17391 :             p = string;
     412           17391 :             len = stringlen;
     413          154217 :             while (len > 0)
     414 ECB             :             {
     415 GIC      136826 :                 stringchars[stringnchars] = p;
     416 CBC      136826 :                 stringmblen[stringnchars] = mblen = pg_mblen(p);
     417          136826 :                 stringnchars++;
     418          136826 :                 p += mblen;
     419          136826 :                 len -= mblen;
     420 ECB             :             }
     421                 : 
     422 GIC       17391 :             setchars = (const char **) palloc(setlen * sizeof(char *));
     423 CBC       17391 :             setmblen = (int *) palloc(setlen * sizeof(int));
     424           17391 :             setnchars = 0;
     425           17391 :             p = set;
     426           17391 :             len = setlen;
     427           35121 :             while (len > 0)
     428 ECB             :             {
     429 GIC       17730 :                 setchars[setnchars] = p;
     430 CBC       17730 :                 setmblen[setnchars] = mblen = pg_mblen(p);
     431           17730 :                 setnchars++;
     432           17730 :                 p += mblen;
     433           17730 :                 len -= mblen;
     434 ECB             :             }
     435                 : 
     436 GIC       17391 :             resultndx = 0;      /* index in stringchars[] */
     437 CBC       17391 :             resultnchars = stringnchars;
     438 ECB             : 
     439 GIC       17391 :             if (doltrim)
     440 ECB             :             {
     441 GIC       28294 :                 while (resultnchars > 0)
     442 ECB             :                 {
     443 GIC       28294 :                     str_pos = stringchars[resultndx];
     444 CBC       28294 :                     str_len = stringmblen[resultndx];
     445           42605 :                     for (i = 0; i < setnchars; i++)
     446 ECB             :                     {
     447 GIC       28354 :                         if (str_len == setmblen[i] &&
     448 CBC       28354 :                             memcmp(str_pos, setchars[i], str_len) == 0)
     449           14043 :                             break;
     450 ECB             :                     }
     451 GIC       28294 :                     if (i >= setnchars)
     452 CBC       14251 :                         break;  /* no match here */
     453           14043 :                     string += str_len;
     454           14043 :                     stringlen -= str_len;
     455           14043 :                     resultndx++;
     456           14043 :                     resultnchars--;
     457 ECB             :                 }
     458                 :             }
     459                 : 
     460 GIC       17391 :             if (dortrim)
     461 ECB             :             {
     462 GIC       37781 :                 while (resultnchars > 0)
     463 ECB             :                 {
     464 GIC       37781 :                     str_pos = stringchars[resultndx + resultnchars - 1];
     465 CBC       37781 :                     str_len = stringmblen[resultndx + resultnchars - 1];
     466           42019 :                     for (i = 0; i < setnchars; i++)
     467 ECB             :                     {
     468 GIC       38588 :                         if (str_len == setmblen[i] &&
     469 CBC       38588 :                             memcmp(str_pos, setchars[i], str_len) == 0)
     470           34350 :                             break;
     471 ECB             :                     }
     472 GIC       37781 :                     if (i >= setnchars)
     473 CBC        3431 :                         break;  /* no match here */
     474           34350 :                     stringlen -= str_len;
     475           34350 :                     resultnchars--;
     476 ECB             :                 }
     477                 :             }
     478                 : 
     479 GIC       17391 :             pfree(stringchars);
     480 CBC       17391 :             pfree(stringmblen);
     481           17391 :             pfree(setchars);
     482           17391 :             pfree(setmblen);
     483 ECB             :         }
     484                 :         else
     485                 :         {
     486                 :             /*
     487                 :              * In the single-byte-encoding case, we don't need such overhead.
     488                 :              */
     489 GIC           6 :             if (doltrim)
     490 ECB             :             {
     491 UIC           0 :                 while (stringlen > 0)
     492 EUB             :                 {
     493 UIC           0 :                     char        str_ch = *string;
     494 EUB             : 
     495 UIC           0 :                     for (i = 0; i < setlen; i++)
     496 EUB             :                     {
     497 UIC           0 :                         if (str_ch == set[i])
     498 UBC           0 :                             break;
     499 EUB             :                     }
     500 UIC           0 :                     if (i >= setlen)
     501 UBC           0 :                         break;  /* no match here */
     502               0 :                     string++;
     503               0 :                     stringlen--;
     504 EUB             :                 }
     505                 :             }
     506                 : 
     507 GIC           6 :             if (dortrim)
     508 ECB             :             {
     509 GIC          12 :                 while (stringlen > 0)
     510 ECB             :                 {
     511 GIC          12 :                     char        str_ch = string[stringlen - 1];
     512 ECB             : 
     513 GIC          18 :                     for (i = 0; i < setlen; i++)
     514 ECB             :                     {
     515 GIC          12 :                         if (str_ch == set[i])
     516 CBC           6 :                             break;
     517 ECB             :                     }
     518 GIC          12 :                     if (i >= setlen)
     519 CBC           6 :                         break;  /* no match here */
     520               6 :                     stringlen--;
     521 ECB             :                 }
     522                 :             }
     523                 :         }
     524                 :     }
     525                 : 
     526                 :     /* Return selected portion of string */
     527 GIC       17397 :     return cstring_to_text_with_len(string, stringlen);
     528 ECB             : }
     529                 : 
     530                 : /*
     531                 :  * Common implementation for bytea versions of btrim, ltrim, rtrim
     532                 :  */
     533                 : bytea *
     534 GIC          18 : dobyteatrim(bytea *string, bytea *set, bool doltrim, bool dortrim)
     535 ECB             : {
     536                 :     bytea      *ret;
     537                 :     char       *ptr,
     538                 :                *end,
     539                 :                *ptr2,
     540                 :                *ptr2start,
     541                 :                *end2;
     542                 :     int         m,
     543                 :                 stringlen,
     544                 :                 setlen;
     545                 : 
     546 GIC          18 :     stringlen = VARSIZE_ANY_EXHDR(string);
     547 CBC          18 :     setlen = VARSIZE_ANY_EXHDR(set);
     548 ECB             : 
     549 GIC          18 :     if (stringlen <= 0 || setlen <= 0)
     550 CBC           6 :         return string;
     551 ECB             : 
     552 GIC          12 :     m = stringlen;
     553 CBC          12 :     ptr = VARDATA_ANY(string);
     554              12 :     end = ptr + stringlen - 1;
     555              12 :     ptr2start = VARDATA_ANY(set);
     556              12 :     end2 = ptr2start + setlen - 1;
     557 ECB             : 
     558 GIC          12 :     if (doltrim)
     559 ECB             :     {
     560 GIC          18 :         while (m > 0)
     561 ECB             :         {
     562 GIC          18 :             ptr2 = ptr2start;
     563 CBC          27 :             while (ptr2 <= end2)
     564 ECB             :             {
     565 GIC          18 :                 if (*ptr == *ptr2)
     566 CBC           9 :                     break;
     567               9 :                 ++ptr2;
     568 ECB             :             }
     569 GIC          18 :             if (ptr2 > end2)
     570 CBC           9 :                 break;
     571               9 :             ptr++;
     572               9 :             m--;
     573 ECB             :         }
     574                 :     }
     575                 : 
     576 GIC          12 :     if (dortrim)
     577 ECB             :     {
     578 GIC          18 :         while (m > 0)
     579 ECB             :         {
     580 GIC          18 :             ptr2 = ptr2start;
     581 CBC          27 :             while (ptr2 <= end2)
     582 ECB             :             {
     583 GIC          18 :                 if (*end == *ptr2)
     584 CBC           9 :                     break;
     585               9 :                 ++ptr2;
     586 ECB             :             }
     587 GIC          18 :             if (ptr2 > end2)
     588 CBC           9 :                 break;
     589               9 :             end--;
     590               9 :             m--;
     591 ECB             :         }
     592                 :     }
     593                 : 
     594 GIC          12 :     ret = (bytea *) palloc(VARHDRSZ + m);
     595 CBC          12 :     SET_VARSIZE(ret, VARHDRSZ + m);
     596              12 :     memcpy(VARDATA(ret), ptr, m);
     597              12 :     return ret;
     598 ECB             : }
     599                 : 
     600                 : /********************************************************************
     601                 :  *
     602                 :  * byteatrim
     603                 :  *
     604                 :  * Syntax:
     605                 :  *
     606                 :  *   bytea byteatrim(bytea string, bytea set)
     607                 :  *
     608                 :  * Purpose:
     609                 :  *
     610                 :  *   Returns string with characters removed from the front and back
     611                 :  *   up to the first character not in set.
     612                 :  *
     613                 :  * Cloned from btrim and modified as required.
     614                 :  ********************************************************************/
     615                 : 
     616                 : Datum
     617 GIC          12 : byteatrim(PG_FUNCTION_ARGS)
     618 ECB             : {
     619 GIC          12 :     bytea      *string = PG_GETARG_BYTEA_PP(0);
     620 CBC          12 :     bytea      *set = PG_GETARG_BYTEA_PP(1);
     621 ECB             :     bytea      *ret;
     622                 : 
     623 GIC          12 :     ret = dobyteatrim(string, set, true, true);
     624 ECB             : 
     625 GIC          12 :     PG_RETURN_BYTEA_P(ret);
     626 ECB             : }
     627                 : 
     628                 : /********************************************************************
     629                 :  *
     630                 :  * bytealtrim
     631                 :  *
     632                 :  * Syntax:
     633                 :  *
     634                 :  *   bytea bytealtrim(bytea string, bytea set)
     635                 :  *
     636                 :  * Purpose:
     637                 :  *
     638                 :  *   Returns string with initial characters removed up to the first
     639                 :  *   character not in set.
     640                 :  *
     641                 :  ********************************************************************/
     642                 : 
     643                 : Datum
     644 GIC           3 : bytealtrim(PG_FUNCTION_ARGS)
     645 ECB             : {
     646 GIC           3 :     bytea      *string = PG_GETARG_BYTEA_PP(0);
     647 CBC           3 :     bytea      *set = PG_GETARG_BYTEA_PP(1);
     648 ECB             :     bytea      *ret;
     649                 : 
     650 GIC           3 :     ret = dobyteatrim(string, set, true, false);
     651 ECB             : 
     652 GIC           3 :     PG_RETURN_BYTEA_P(ret);
     653 ECB             : }
     654                 : 
     655                 : /********************************************************************
     656                 :  *
     657                 :  * byteartrim
     658                 :  *
     659                 :  * Syntax:
     660                 :  *
     661                 :  *   bytea byteartrim(bytea string, bytea set)
     662                 :  *
     663                 :  * Purpose:
     664                 :  *
     665                 :  *   Returns string with final characters removed after the last
     666                 :  *   character not in set.
     667                 :  *
     668                 :  ********************************************************************/
     669                 : 
     670                 : Datum
     671 GIC           3 : byteartrim(PG_FUNCTION_ARGS)
     672 ECB             : {
     673 GIC           3 :     bytea      *string = PG_GETARG_BYTEA_PP(0);
     674 CBC           3 :     bytea      *set = PG_GETARG_BYTEA_PP(1);
     675 ECB             :     bytea      *ret;
     676                 : 
     677 GIC           3 :     ret = dobyteatrim(string, set, false, true);
     678 ECB             : 
     679 GIC           3 :     PG_RETURN_BYTEA_P(ret);
     680 ECB             : }
     681                 : 
     682                 : /********************************************************************
     683                 :  *
     684                 :  * ltrim
     685                 :  *
     686                 :  * Syntax:
     687                 :  *
     688                 :  *   text ltrim(text string, text set)
     689                 :  *
     690                 :  * Purpose:
     691                 :  *
     692                 :  *   Returns string with initial characters removed up to the first
     693                 :  *   character not in set.
     694                 :  *
     695                 :  ********************************************************************/
     696                 : 
     697                 : Datum
     698 GIC       13956 : ltrim(PG_FUNCTION_ARGS)
     699 ECB             : {
     700 GIC       13956 :     text       *string = PG_GETARG_TEXT_PP(0);
     701 CBC       13956 :     text       *set = PG_GETARG_TEXT_PP(1);
     702 ECB             :     text       *ret;
     703                 : 
     704 GIC       27912 :     ret = dotrim(VARDATA_ANY(string), VARSIZE_ANY_EXHDR(string),
     705 CBC       27912 :                  VARDATA_ANY(set), VARSIZE_ANY_EXHDR(set),
     706 ECB             :                  true, false);
     707                 : 
     708 GIC       13956 :     PG_RETURN_TEXT_P(ret);
     709 ECB             : }
     710                 : 
     711                 : /********************************************************************
     712                 :  *
     713                 :  * ltrim1 --- ltrim with set fixed as ' '
     714                 :  *
     715                 :  ********************************************************************/
     716                 : 
     717                 : Datum
     718 GIC           4 : ltrim1(PG_FUNCTION_ARGS)
     719 ECB             : {
     720 GIC           4 :     text       *string = PG_GETARG_TEXT_PP(0);
     721 ECB             :     text       *ret;
     722                 : 
     723 GIC           4 :     ret = dotrim(VARDATA_ANY(string), VARSIZE_ANY_EXHDR(string),
     724 ECB             :                  " ", 1,
     725                 :                  true, false);
     726                 : 
     727 GIC           4 :     PG_RETURN_TEXT_P(ret);
     728 ECB             : }
     729                 : 
     730                 : /********************************************************************
     731                 :  *
     732                 :  * rtrim
     733                 :  *
     734                 :  * Syntax:
     735                 :  *
     736                 :  *   text rtrim(text string, text set)
     737                 :  *
     738                 :  * Purpose:
     739                 :  *
     740                 :  *   Returns string with final characters removed after the last
     741                 :  *   character not in set.
     742                 :  *
     743                 :  ********************************************************************/
     744                 : 
     745                 : Datum
     746 GIC         387 : rtrim(PG_FUNCTION_ARGS)
     747 ECB             : {
     748 GIC         387 :     text       *string = PG_GETARG_TEXT_PP(0);
     749 CBC         387 :     text       *set = PG_GETARG_TEXT_PP(1);
     750 ECB             :     text       *ret;
     751                 : 
     752 GIC         774 :     ret = dotrim(VARDATA_ANY(string), VARSIZE_ANY_EXHDR(string),
     753 CBC         774 :                  VARDATA_ANY(set), VARSIZE_ANY_EXHDR(set),
     754 ECB             :                  false, true);
     755                 : 
     756 GIC         387 :     PG_RETURN_TEXT_P(ret);
     757 ECB             : }
     758                 : 
     759                 : /********************************************************************
     760                 :  *
     761                 :  * rtrim1 --- rtrim with set fixed as ' '
     762                 :  *
     763                 :  ********************************************************************/
     764                 : 
     765                 : Datum
     766 GIC        2759 : rtrim1(PG_FUNCTION_ARGS)
     767 ECB             : {
     768 GIC        2759 :     text       *string = PG_GETARG_TEXT_PP(0);
     769 ECB             :     text       *ret;
     770                 : 
     771 GIC        2759 :     ret = dotrim(VARDATA_ANY(string), VARSIZE_ANY_EXHDR(string),
     772 ECB             :                  " ", 1,
     773                 :                  false, true);
     774                 : 
     775 GIC        2759 :     PG_RETURN_TEXT_P(ret);
     776 ECB             : }
     777                 : 
     778                 : 
     779                 : /********************************************************************
     780                 :  *
     781                 :  * translate
     782                 :  *
     783                 :  * Syntax:
     784                 :  *
     785                 :  *   text translate(text string, text from, text to)
     786                 :  *
     787                 :  * Purpose:
     788                 :  *
     789                 :  *   Returns string after replacing all occurrences of characters in from
     790                 :  *   with the corresponding character in to.  If from is longer than to,
     791                 :  *   occurrences of the extra characters in from are deleted.
     792                 :  *   Improved by Edwin Ramirez <ramirez@doc.mssm.edu>.
     793                 :  *
     794                 :  ********************************************************************/
     795                 : 
     796                 : Datum
     797 GIC          17 : translate(PG_FUNCTION_ARGS)
     798 ECB             : {
     799 GIC          17 :     text       *string = PG_GETARG_TEXT_PP(0);
     800 CBC          17 :     text       *from = PG_GETARG_TEXT_PP(1);
     801              17 :     text       *to = PG_GETARG_TEXT_PP(2);
     802 ECB             :     text       *result;
     803                 :     char       *from_ptr,
     804                 :                *to_ptr,
     805                 :                *to_end;
     806                 :     char       *source,
     807                 :                *target;
     808                 :     int         m,
     809                 :                 fromlen,
     810                 :                 tolen,
     811                 :                 retlen,
     812                 :                 i;
     813                 :     int         bytelen;
     814                 :     int         len;
     815                 :     int         source_len;
     816                 :     int         from_index;
     817                 : 
     818 GIC          17 :     m = VARSIZE_ANY_EXHDR(string);
     819 CBC          17 :     if (m <= 0)
     820               3 :         PG_RETURN_TEXT_P(string);
     821              14 :     source = VARDATA_ANY(string);
     822 ECB             : 
     823 GIC          14 :     fromlen = VARSIZE_ANY_EXHDR(from);
     824 CBC          14 :     from_ptr = VARDATA_ANY(from);
     825              14 :     tolen = VARSIZE_ANY_EXHDR(to);
     826              14 :     to_ptr = VARDATA_ANY(to);
     827              14 :     to_end = to_ptr + tolen;
     828 ECB             : 
     829                 :     /*
     830                 :      * The worst-case expansion is to substitute a max-length character for a
     831                 :      * single-byte character at each position of the string.
     832                 :      */
     833 GIC          14 :     if (unlikely(pg_mul_s32_overflow(pg_database_encoding_max_length(), m,
     834 CBC          14 :                                      &bytelen)) ||
     835              14 :         unlikely(pg_add_s32_overflow(bytelen, VARHDRSZ, &bytelen)) ||
     836              14 :         unlikely(!AllocSizeIsValid(bytelen)))
     837 LBC           0 :         ereport(ERROR,
     838 EUB             :                 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
     839                 :                  errmsg("requested length too large")));
     840                 : 
     841 GIC          14 :     result = (text *) palloc(bytelen);
     842 ECB             : 
     843 GIC          14 :     target = VARDATA(result);
     844 CBC          14 :     retlen = 0;
     845 ECB             : 
     846 GIC         140 :     while (m > 0)
     847 ECB             :     {
     848 GIC         126 :         source_len = pg_mblen(source);
     849 CBC         126 :         from_index = 0;
     850 ECB             : 
     851 GIC         342 :         for (i = 0; i < fromlen; i += len)
     852 ECB             :         {
     853 GIC         247 :             len = pg_mblen(&from_ptr[i]);
     854 CBC         247 :             if (len == source_len &&
     855             247 :                 memcmp(source, &from_ptr[i], len) == 0)
     856              31 :                 break;
     857 ECB             : 
     858 GIC         216 :             from_index++;
     859 ECB             :         }
     860 GIC         126 :         if (i < fromlen)
     861 ECB             :         {
     862                 :             /* substitute, or delete if no corresponding "to" character */
     863 GIC          31 :             char       *p = to_ptr;
     864 ECB             : 
     865 GIC          48 :             for (i = 0; i < from_index; i++)
     866 ECB             :             {
     867 GIC          20 :                 if (p >= to_end)
     868 CBC           3 :                     break;
     869              17 :                 p += pg_mblen(p);
     870 ECB             :             }
     871 GIC          31 :             if (p < to_end)
     872 ECB             :             {
     873 GIC          25 :                 len = pg_mblen(p);
     874 CBC          25 :                 memcpy(target, p, len);
     875              25 :                 target += len;
     876              25 :                 retlen += len;
     877 ECB             :             }
     878                 :         }
     879                 :         else
     880                 :         {
     881                 :             /* no match, so copy */
     882 GIC          95 :             memcpy(target, source, source_len);
     883 CBC          95 :             target += source_len;
     884              95 :             retlen += source_len;
     885 ECB             :         }
     886                 : 
     887 GIC         126 :         source += source_len;
     888 CBC         126 :         m -= source_len;
     889 ECB             :     }
     890                 : 
     891 GIC          14 :     SET_VARSIZE(result, retlen + VARHDRSZ);
     892 ECB             : 
     893                 :     /*
     894                 :      * The function result is probably much bigger than needed, if we're using
     895                 :      * a multibyte encoding, but it's not worth reallocating it; the result
     896                 :      * probably won't live long anyway.
     897                 :      */
     898                 : 
     899 GIC          14 :     PG_RETURN_TEXT_P(result);
     900 ECB             : }
     901                 : 
     902                 : /********************************************************************
     903                 :  *
     904                 :  * ascii
     905                 :  *
     906                 :  * Syntax:
     907                 :  *
     908                 :  *   int ascii(text string)
     909                 :  *
     910                 :  * Purpose:
     911                 :  *
     912                 :  *   Returns the decimal representation of the first character from
     913                 :  *   string.
     914                 :  *   If the string is empty we return 0.
     915                 :  *   If the database encoding is UTF8, we return the Unicode codepoint.
     916                 :  *   If the database encoding is any other multi-byte encoding, we
     917                 :  *   return the value of the first byte if it is an ASCII character
     918                 :  *   (range 1 .. 127), or raise an error.
     919                 :  *   For all other encodings we return the value of the first byte,
     920                 :  *   (range 1..255).
     921                 :  *
     922                 :  ********************************************************************/
     923                 : 
     924                 : Datum
     925 GIC          29 : ascii(PG_FUNCTION_ARGS)
     926 ECB             : {
     927 GIC          29 :     text       *string = PG_GETARG_TEXT_PP(0);
     928 CBC          29 :     int         encoding = GetDatabaseEncoding();
     929 ECB             :     unsigned char *data;
     930                 : 
     931 GIC          29 :     if (VARSIZE_ANY_EXHDR(string) <= 0)
     932 CBC           3 :         PG_RETURN_INT32(0);
     933 ECB             : 
     934 GIC          26 :     data = (unsigned char *) VARDATA_ANY(string);
     935 ECB             : 
     936 GIC          26 :     if (encoding == PG_UTF8 && *data > 127)
     937 ECB             :     {
     938                 :         /* return the code point for Unicode */
     939                 : 
     940 UIC           0 :         int         result = 0,
     941 UBC           0 :                     tbytes = 0,
     942 EUB             :                     i;
     943                 : 
     944 UIC           0 :         if (*data >= 0xF0)
     945 EUB             :         {
     946 UIC           0 :             result = *data & 0x07;
     947 UBC           0 :             tbytes = 3;
     948 EUB             :         }
     949 UIC           0 :         else if (*data >= 0xE0)
     950 EUB             :         {
     951 UIC           0 :             result = *data & 0x0F;
     952 UBC           0 :             tbytes = 2;
     953 EUB             :         }
     954                 :         else
     955                 :         {
     956 UIC           0 :             Assert(*data > 0xC0);
     957 UBC           0 :             result = *data & 0x1f;
     958               0 :             tbytes = 1;
     959 EUB             :         }
     960                 : 
     961 UIC           0 :         Assert(tbytes > 0);
     962 EUB             : 
     963 UIC           0 :         for (i = 1; i <= tbytes; i++)
     964 EUB             :         {
     965 UIC           0 :             Assert((data[i] & 0xC0) == 0x80);
     966 UBC           0 :             result = (result << 6) + (data[i] & 0x3f);
     967 EUB             :         }
     968                 : 
     969 UIC           0 :         PG_RETURN_INT32(result);
     970 EUB             :     }
     971                 :     else
     972                 :     {
     973 GIC          26 :         if (pg_encoding_max_length(encoding) > 1 && *data > 127)
     974 LBC           0 :             ereport(ERROR,
     975 EUB             :                     (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
     976                 :                      errmsg("requested character too large")));
     977                 : 
     978                 : 
     979 GIC          26 :         PG_RETURN_INT32((int32) *data);
     980 ECB             :     }
     981                 : }
     982                 : 
     983                 : /********************************************************************
     984                 :  *
     985                 :  * chr
     986                 :  *
     987                 :  * Syntax:
     988                 :  *
     989                 :  *   text chr(int val)
     990                 :  *
     991                 :  * Purpose:
     992                 :  *
     993                 :  *  Returns the character having the binary equivalent to val.
     994                 :  *
     995                 :  * For UTF8 we treat the argument as a Unicode code point.
     996                 :  * For other multi-byte encodings we raise an error for arguments
     997                 :  * outside the strict ASCII range (1..127).
     998                 :  *
     999                 :  * It's important that we don't ever return a value that is not valid
    1000                 :  * in the database encoding, so that this doesn't become a way for
    1001                 :  * invalid data to enter the database.
    1002                 :  *
    1003                 :  ********************************************************************/
    1004                 : 
    1005                 : Datum
    1006 GIC      272598 : chr         (PG_FUNCTION_ARGS)
    1007 ECB             : {
    1008 GIC      272598 :     int32       arg = PG_GETARG_INT32(0);
    1009 ECB             :     uint32      cvalue;
    1010                 :     text       *result;
    1011 GIC      272598 :     int         encoding = GetDatabaseEncoding();
    1012 ECB             : 
    1013                 :     /*
    1014                 :      * Error out on arguments that make no sense or that we can't validly
    1015                 :      * represent in the encoding.
    1016                 :      */
    1017 GIC      272598 :     if (arg < 0)
    1018 LBC           0 :         ereport(ERROR,
    1019 EUB             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1020                 :                  errmsg("character number must be positive")));
    1021 GIC      272598 :     else if (arg == 0)
    1022 CBC           3 :         ereport(ERROR,
    1023 ECB             :                 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
    1024                 :                  errmsg("null character not permitted")));
    1025                 : 
    1026 GIC      272595 :     cvalue = arg;
    1027 ECB             : 
    1028 GIC      272595 :     if (encoding == PG_UTF8 && cvalue > 127)
    1029 LBC           0 :     {
    1030 EUB             :         /* for Unicode we treat the argument as a code point */
    1031                 :         int         bytes;
    1032                 :         unsigned char *wch;
    1033                 : 
    1034                 :         /*
    1035                 :          * We only allow valid Unicode code points; per RFC3629 that stops at
    1036                 :          * U+10FFFF, even though 4-byte UTF8 sequences can hold values up to
    1037                 :          * U+1FFFFF.
    1038                 :          */
    1039 UIC           0 :         if (cvalue > 0x0010ffff)
    1040 UBC           0 :             ereport(ERROR,
    1041 EUB             :                     (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
    1042                 :                      errmsg("requested character too large for encoding: %u",
    1043                 :                             cvalue)));
    1044                 : 
    1045 UIC           0 :         if (cvalue > 0xffff)
    1046 UBC           0 :             bytes = 4;
    1047               0 :         else if (cvalue > 0x07ff)
    1048               0 :             bytes = 3;
    1049 EUB             :         else
    1050 UIC           0 :             bytes = 2;
    1051 EUB             : 
    1052 UIC           0 :         result = (text *) palloc(VARHDRSZ + bytes);
    1053 UBC           0 :         SET_VARSIZE(result, VARHDRSZ + bytes);
    1054               0 :         wch = (unsigned char *) VARDATA(result);
    1055 EUB             : 
    1056 UIC           0 :         if (bytes == 2)
    1057 EUB             :         {
    1058 UIC           0 :             wch[0] = 0xC0 | ((cvalue >> 6) & 0x1F);
    1059 UBC           0 :             wch[1] = 0x80 | (cvalue & 0x3F);
    1060 EUB             :         }
    1061 UIC           0 :         else if (bytes == 3)
    1062 EUB             :         {
    1063 UIC           0 :             wch[0] = 0xE0 | ((cvalue >> 12) & 0x0F);
    1064 UBC           0 :             wch[1] = 0x80 | ((cvalue >> 6) & 0x3F);
    1065               0 :             wch[2] = 0x80 | (cvalue & 0x3F);
    1066 EUB             :         }
    1067                 :         else
    1068                 :         {
    1069 UIC           0 :             wch[0] = 0xF0 | ((cvalue >> 18) & 0x07);
    1070 UBC           0 :             wch[1] = 0x80 | ((cvalue >> 12) & 0x3F);
    1071               0 :             wch[2] = 0x80 | ((cvalue >> 6) & 0x3F);
    1072               0 :             wch[3] = 0x80 | (cvalue & 0x3F);
    1073 EUB             :         }
    1074                 : 
    1075                 :         /*
    1076                 :          * The preceding range check isn't sufficient, because UTF8 excludes
    1077                 :          * Unicode "surrogate pair" codes.  Make sure what we created is valid
    1078                 :          * UTF8.
    1079                 :          */
    1080 UIC           0 :         if (!pg_utf8_islegal(wch, bytes))
    1081 UBC           0 :             ereport(ERROR,
    1082 EUB             :                     (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
    1083                 :                      errmsg("requested character not valid for encoding: %u",
    1084                 :                             cvalue)));
    1085                 :     }
    1086                 :     else
    1087                 :     {
    1088                 :         bool        is_mb;
    1089                 : 
    1090 GIC      272595 :         is_mb = pg_encoding_max_length(encoding) > 1;
    1091 ECB             : 
    1092 GIC      272595 :         if ((is_mb && (cvalue > 127)) || (!is_mb && (cvalue > 255)))
    1093 LBC           0 :             ereport(ERROR,
    1094 EUB             :                     (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
    1095                 :                      errmsg("requested character too large for encoding: %u",
    1096                 :                             cvalue)));
    1097                 : 
    1098 GIC      272595 :         result = (text *) palloc(VARHDRSZ + 1);
    1099 CBC      272595 :         SET_VARSIZE(result, VARHDRSZ + 1);
    1100          272595 :         *VARDATA(result) = (char) cvalue;
    1101 ECB             :     }
    1102                 : 
    1103 GIC      272595 :     PG_RETURN_TEXT_P(result);
    1104 ECB             : }
    1105                 : 
    1106                 : /********************************************************************
    1107                 :  *
    1108                 :  * repeat
    1109                 :  *
    1110                 :  * Syntax:
    1111                 :  *
    1112                 :  *   text repeat(text string, int val)
    1113                 :  *
    1114                 :  * Purpose:
    1115                 :  *
    1116                 :  *  Repeat string by val.
    1117                 :  *
    1118                 :  ********************************************************************/
    1119                 : 
    1120                 : Datum
    1121 GIC       21002 : repeat(PG_FUNCTION_ARGS)
    1122 ECB             : {
    1123 GIC       21002 :     text       *string = PG_GETARG_TEXT_PP(0);
    1124 CBC       21002 :     int32       count = PG_GETARG_INT32(1);
    1125 ECB             :     text       *result;
    1126                 :     int         slen,
    1127                 :                 tlen;
    1128                 :     int         i;
    1129                 :     char       *cp,
    1130                 :                *sp;
    1131                 : 
    1132 GIC       21002 :     if (count < 0)
    1133 CBC           3 :         count = 0;
    1134 ECB             : 
    1135 GIC       21002 :     slen = VARSIZE_ANY_EXHDR(string);
    1136 ECB             : 
    1137 GIC       21002 :     if (unlikely(pg_mul_s32_overflow(count, slen, &tlen)) ||
    1138 CBC       21002 :         unlikely(pg_add_s32_overflow(tlen, VARHDRSZ, &tlen)) ||
    1139           21002 :         unlikely(!AllocSizeIsValid(tlen)))
    1140 LBC           0 :         ereport(ERROR,
    1141 EUB             :                 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
    1142                 :                  errmsg("requested length too large")));
    1143                 : 
    1144 GIC       21002 :     result = (text *) palloc(tlen);
    1145 ECB             : 
    1146 GIC       21002 :     SET_VARSIZE(result, tlen);
    1147 CBC       21002 :     cp = VARDATA(result);
    1148           21002 :     sp = VARDATA_ANY(string);
    1149        19076835 :     for (i = 0; i < count; i++)
    1150 ECB             :     {
    1151 GIC    19055833 :         memcpy(cp, sp, slen);
    1152 CBC    19055833 :         cp += slen;
    1153        19055833 :         CHECK_FOR_INTERRUPTS();
    1154 ECB             :     }
    1155                 : 
    1156 GIC       21002 :     PG_RETURN_TEXT_P(result);
    1157 ECB             : }
        

Generated by: LCOV version v1.16-55-g56c0a2a