LCOV - code coverage report
Current view: top level - src/backend/utils/adt - char.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 79.6 % 103 82
Test Date: 2026-01-26 10:56:24 Functions: 71.4 % 14 10
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 56.5 % 46 26

             Branch data     Line data    Source code
       1                 :             : /*-------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * char.c
       4                 :             :  *        Functions for the built-in type "char" (not to be confused with
       5                 :             :  *        bpchar, which is the SQL CHAR(n) type).
       6                 :             :  *
       7                 :             :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
       8                 :             :  * Portions Copyright (c) 1994, Regents of the University of California
       9                 :             :  *
      10                 :             :  *
      11                 :             :  * IDENTIFICATION
      12                 :             :  *        src/backend/utils/adt/char.c
      13                 :             :  *
      14                 :             :  *-------------------------------------------------------------------------
      15                 :             :  */
      16                 :             : #include "postgres.h"
      17                 :             : 
      18                 :             : #include <limits.h>
      19                 :             : 
      20                 :             : #include "libpq/pqformat.h"
      21                 :             : #include "utils/fmgrprotos.h"
      22                 :             : #include "varatt.h"
      23                 :             : 
      24                 :             : #define ISOCTAL(c)   (((c) >= '0') && ((c) <= '7'))
      25                 :             : #define TOOCTAL(c)   ((c) + '0')
      26                 :             : #define FROMOCTAL(c) ((unsigned char) (c) - '0')
      27                 :             : 
      28                 :             : 
      29                 :             : /*****************************************************************************
      30                 :             :  *       USER I/O ROUTINES                                                                                                               *
      31                 :             :  *****************************************************************************/
      32                 :             : 
      33                 :             : /*
      34                 :             :  *              charin                  - converts "x" to 'x'
      35                 :             :  *
      36                 :             :  * This accepts the formats charout produces.  If we have multibyte input
      37                 :             :  * that is not in the form '\ooo', then we take its first byte as the value
      38                 :             :  * and silently discard the rest; this is a backwards-compatibility provision.
      39                 :             :  */
      40                 :             : Datum
      41                 :       24156 : charin(PG_FUNCTION_ARGS)
      42                 :             : {
      43                 :       24156 :         char       *ch = PG_GETARG_CSTRING(0);
      44                 :             : 
      45   [ +  +  +  - ]:       24156 :         if (strlen(ch) == 4 && ch[0] == '\\' &&
      46   [ +  -  +  -  :           4 :                 ISOCTAL(ch[1]) && ISOCTAL(ch[2]) && ISOCTAL(ch[3]))
          +  -  +  -  +  
                -  -  + ]
      47                 :           4 :                 PG_RETURN_CHAR((FROMOCTAL(ch[1]) << 6) +
      48                 :             :                                            (FROMOCTAL(ch[2]) << 3) +
      49                 :             :                                            FROMOCTAL(ch[3]));
      50                 :             :         /* This will do the right thing for a zero-length input string */
      51                 :       24152 :         PG_RETURN_CHAR(ch[0]);
      52                 :       24156 : }
      53                 :             : 
      54                 :             : /*
      55                 :             :  *              charout                 - converts 'x' to "x"
      56                 :             :  *
      57                 :             :  * The possible output formats are:
      58                 :             :  * 1. 0x00 is represented as an empty string.
      59                 :             :  * 2. 0x01..0x7F are represented as a single ASCII byte.
      60                 :             :  * 3. 0x80..0xFF are represented as \ooo (backslash and 3 octal digits).
      61                 :             :  * Case 3 is meant to match the traditional "escape" format of bytea.
      62                 :             :  */
      63                 :             : Datum
      64                 :        6668 : charout(PG_FUNCTION_ARGS)
      65                 :             : {
      66                 :        6668 :         char            ch = PG_GETARG_CHAR(0);
      67                 :        6668 :         char       *result = (char *) palloc(5);
      68                 :             : 
      69         [ +  + ]:        6668 :         if (IS_HIGHBIT_SET(ch))
      70                 :             :         {
      71                 :           2 :                 result[0] = '\\';
      72                 :           2 :                 result[1] = TOOCTAL(((unsigned char) ch) >> 6);
      73                 :           2 :                 result[2] = TOOCTAL((((unsigned char) ch) >> 3) & 07);
      74                 :           2 :                 result[3] = TOOCTAL(((unsigned char) ch) & 07);
      75                 :           2 :                 result[4] = '\0';
      76                 :           2 :         }
      77                 :             :         else
      78                 :             :         {
      79                 :             :                 /* This produces acceptable results for 0x00 as well */
      80                 :        6666 :                 result[0] = ch;
      81                 :        6666 :                 result[1] = '\0';
      82                 :             :         }
      83                 :       13336 :         PG_RETURN_CSTRING(result);
      84                 :        6668 : }
      85                 :             : 
      86                 :             : /*
      87                 :             :  *              charrecv                        - converts external binary format to char
      88                 :             :  *
      89                 :             :  * The external representation is one byte, with no character set
      90                 :             :  * conversion.  This is somewhat dubious, perhaps, but in many
      91                 :             :  * cases people use char for a 1-byte binary type.
      92                 :             :  */
      93                 :             : Datum
      94                 :           0 : charrecv(PG_FUNCTION_ARGS)
      95                 :             : {
      96                 :           0 :         StringInfo      buf = (StringInfo) PG_GETARG_POINTER(0);
      97                 :             : 
      98                 :           0 :         PG_RETURN_CHAR(pq_getmsgbyte(buf));
      99                 :           0 : }
     100                 :             : 
     101                 :             : /*
     102                 :             :  *              charsend                        - converts char to binary format
     103                 :             :  */
     104                 :             : Datum
     105                 :           0 : charsend(PG_FUNCTION_ARGS)
     106                 :             : {
     107                 :           0 :         char            arg1 = PG_GETARG_CHAR(0);
     108                 :           0 :         StringInfoData buf;
     109                 :             : 
     110                 :           0 :         pq_begintypsend(&buf);
     111                 :           0 :         pq_sendbyte(&buf, arg1);
     112                 :           0 :         PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
     113                 :           0 : }
     114                 :             : 
     115                 :             : /*****************************************************************************
     116                 :             :  *       PUBLIC ROUTINES                                                                                                                 *
     117                 :             :  *****************************************************************************/
     118                 :             : 
     119                 :             : /*
     120                 :             :  * NOTE: comparisons are done as though char is unsigned (uint8).
     121                 :             :  * Conversions to and from integer are done as though char is signed (int8).
     122                 :             :  *
     123                 :             :  * You wanted consistency?
     124                 :             :  */
     125                 :             : 
     126                 :             : Datum
     127                 :      478609 : chareq(PG_FUNCTION_ARGS)
     128                 :             : {
     129                 :      478609 :         char            arg1 = PG_GETARG_CHAR(0);
     130                 :      478609 :         char            arg2 = PG_GETARG_CHAR(1);
     131                 :             : 
     132                 :      957218 :         PG_RETURN_BOOL(arg1 == arg2);
     133                 :      478609 : }
     134                 :             : 
     135                 :             : Datum
     136                 :      187047 : charne(PG_FUNCTION_ARGS)
     137                 :             : {
     138                 :      187047 :         char            arg1 = PG_GETARG_CHAR(0);
     139                 :      187047 :         char            arg2 = PG_GETARG_CHAR(1);
     140                 :             : 
     141                 :      374094 :         PG_RETURN_BOOL(arg1 != arg2);
     142                 :      187047 : }
     143                 :             : 
     144                 :             : Datum
     145                 :         516 : charlt(PG_FUNCTION_ARGS)
     146                 :             : {
     147                 :         516 :         char            arg1 = PG_GETARG_CHAR(0);
     148                 :         516 :         char            arg2 = PG_GETARG_CHAR(1);
     149                 :             : 
     150                 :        1032 :         PG_RETURN_BOOL((uint8) arg1 < (uint8) arg2);
     151                 :         516 : }
     152                 :             : 
     153                 :             : Datum
     154                 :         404 : charle(PG_FUNCTION_ARGS)
     155                 :             : {
     156                 :         404 :         char            arg1 = PG_GETARG_CHAR(0);
     157                 :         404 :         char            arg2 = PG_GETARG_CHAR(1);
     158                 :             : 
     159                 :         808 :         PG_RETURN_BOOL((uint8) arg1 <= (uint8) arg2);
     160                 :         404 : }
     161                 :             : 
     162                 :             : Datum
     163                 :         507 : chargt(PG_FUNCTION_ARGS)
     164                 :             : {
     165                 :         507 :         char            arg1 = PG_GETARG_CHAR(0);
     166                 :         507 :         char            arg2 = PG_GETARG_CHAR(1);
     167                 :             : 
     168                 :        1014 :         PG_RETURN_BOOL((uint8) arg1 > (uint8) arg2);
     169                 :         507 : }
     170                 :             : 
     171                 :             : Datum
     172                 :         355 : charge(PG_FUNCTION_ARGS)
     173                 :             : {
     174                 :         355 :         char            arg1 = PG_GETARG_CHAR(0);
     175                 :         355 :         char            arg2 = PG_GETARG_CHAR(1);
     176                 :             : 
     177                 :         710 :         PG_RETURN_BOOL((uint8) arg1 >= (uint8) arg2);
     178                 :         355 : }
     179                 :             : 
     180                 :             : 
     181                 :             : Datum
     182                 :           0 : chartoi4(PG_FUNCTION_ARGS)
     183                 :             : {
     184                 :           0 :         char            arg1 = PG_GETARG_CHAR(0);
     185                 :             : 
     186                 :           0 :         PG_RETURN_INT32((int32) ((int8) arg1));
     187                 :           0 : }
     188                 :             : 
     189                 :             : Datum
     190                 :           0 : i4tochar(PG_FUNCTION_ARGS)
     191                 :             : {
     192                 :           0 :         int32           arg1 = PG_GETARG_INT32(0);
     193                 :             : 
     194         [ #  # ]:           0 :         if (arg1 < SCHAR_MIN || arg1 > SCHAR_MAX)
     195   [ #  #  #  # ]:           0 :                 ereport(ERROR,
     196                 :             :                                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     197                 :             :                                  errmsg("\"char\" out of range")));
     198                 :             : 
     199                 :           0 :         PG_RETURN_CHAR((int8) arg1);
     200                 :           0 : }
     201                 :             : 
     202                 :             : 
     203                 :             : Datum
     204                 :         352 : text_char(PG_FUNCTION_ARGS)
     205                 :             : {
     206                 :         352 :         text       *arg1 = PG_GETARG_TEXT_PP(0);
     207                 :         352 :         char       *ch = VARDATA_ANY(arg1);
     208                 :         352 :         char            result;
     209                 :             : 
     210                 :             :         /*
     211                 :             :          * Conversion rules are the same as in charin(), but here we need to
     212                 :             :          * handle the empty-string case honestly.
     213                 :             :          */
     214   [ +  +  +  - ]:         352 :         if (VARSIZE_ANY_EXHDR(arg1) == 4 && ch[0] == '\\' &&
     215   [ +  -  +  -  :           1 :                 ISOCTAL(ch[1]) && ISOCTAL(ch[2]) && ISOCTAL(ch[3]))
          +  -  +  -  +  
                -  -  + ]
     216                 :           3 :                 result = (FROMOCTAL(ch[1]) << 6) +
     217                 :           2 :                         (FROMOCTAL(ch[2]) << 3) +
     218                 :           1 :                         FROMOCTAL(ch[3]);
     219         [ +  + ]:         351 :         else if (VARSIZE_ANY_EXHDR(arg1) > 0)
     220                 :         350 :                 result = ch[0];
     221                 :             :         else
     222                 :           1 :                 result = '\0';
     223                 :             : 
     224                 :         704 :         PG_RETURN_CHAR(result);
     225                 :         352 : }
     226                 :             : 
     227                 :             : Datum
     228                 :           3 : char_text(PG_FUNCTION_ARGS)
     229                 :             : {
     230                 :           3 :         char            arg1 = PG_GETARG_CHAR(0);
     231                 :           3 :         text       *result = palloc(VARHDRSZ + 4);
     232                 :             : 
     233                 :             :         /*
     234                 :             :          * Conversion rules are the same as in charout(), but here we need to be
     235                 :             :          * honest about converting 0x00 to an empty string.
     236                 :             :          */
     237         [ +  + ]:           3 :         if (IS_HIGHBIT_SET(arg1))
     238                 :             :         {
     239                 :           1 :                 SET_VARSIZE(result, VARHDRSZ + 4);
     240                 :           1 :                 (VARDATA(result))[0] = '\\';
     241                 :           1 :                 (VARDATA(result))[1] = TOOCTAL(((unsigned char) arg1) >> 6);
     242                 :           1 :                 (VARDATA(result))[2] = TOOCTAL((((unsigned char) arg1) >> 3) & 07);
     243                 :           1 :                 (VARDATA(result))[3] = TOOCTAL(((unsigned char) arg1) & 07);
     244                 :           1 :         }
     245         [ +  + ]:           2 :         else if (arg1 != '\0')
     246                 :             :         {
     247                 :           1 :                 SET_VARSIZE(result, VARHDRSZ + 1);
     248                 :           1 :                 *(VARDATA(result)) = arg1;
     249                 :           1 :         }
     250                 :             :         else
     251                 :           1 :                 SET_VARSIZE(result, VARHDRSZ);
     252                 :             : 
     253                 :           6 :         PG_RETURN_TEXT_P(result);
     254                 :           3 : }
        

Generated by: LCOV version 2.3.2-1