LCOV - differential code coverage report
Current view: top level - src/backend/utils/adt - char.c (source / functions) Coverage Total Hit UIC UBC GIC CBC EUB ECB
Current: Differential Code Coverage HEAD vs 15 Lines: 81.0 % 84 68 13 3 41 27 13 41
Current Date: 2023-04-08 15:15:32 Functions: 71.4 % 14 10 4 10 4 10
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  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-2023, 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/builtins.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 GIC     4655427 : charin(PG_FUNCTION_ARGS)
      42 ECB             : {
      43 GIC     4655427 :     char       *ch = PG_GETARG_CSTRING(0);
      44 ECB             : 
      45 GIC     4655427 :     if (strlen(ch) == 4 && ch[0] == '\\' &&
      46 CBC          12 :         ISOCTAL(ch[1]) && ISOCTAL(ch[2]) && ISOCTAL(ch[3]))
      47              12 :         PG_RETURN_CHAR((FROMOCTAL(ch[1]) << 6) +
      48 ECB             :                        (FROMOCTAL(ch[2]) << 3) +
      49                 :                        FROMOCTAL(ch[3]));
      50                 :     /* This will do the right thing for a zero-length input string */
      51 GIC     4655415 :     PG_RETURN_CHAR(ch[0]);
      52 ECB             : }
      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 GIC      860899 : charout(PG_FUNCTION_ARGS)
      65 ECB             : {
      66 GIC      860899 :     char        ch = PG_GETARG_CHAR(0);
      67 CBC      860899 :     char       *result = (char *) palloc(5);
      68 ECB             : 
      69 GIC      860899 :     if (IS_HIGHBIT_SET(ch))
      70 ECB             :     {
      71 GIC           6 :         result[0] = '\\';
      72 CBC           6 :         result[1] = TOOCTAL(((unsigned char) ch) >> 6);
      73               6 :         result[2] = TOOCTAL((((unsigned char) ch) >> 3) & 07);
      74               6 :         result[3] = TOOCTAL(((unsigned char) ch) & 07);
      75               6 :         result[4] = '\0';
      76 ECB             :     }
      77                 :     else
      78                 :     {
      79                 :         /* This produces acceptable results for 0x00 as well */
      80 GIC      860893 :         result[0] = ch;
      81 CBC      860893 :         result[1] = '\0';
      82 ECB             :     }
      83 GIC      860899 :     PG_RETURN_CSTRING(result);
      84 ECB             : }
      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 UIC           0 : charrecv(PG_FUNCTION_ARGS)
      95 EUB             : {
      96 UIC           0 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
      97 EUB             : 
      98 UIC           0 :     PG_RETURN_CHAR(pq_getmsgbyte(buf));
      99 EUB             : }
     100                 : 
     101                 : /*
     102                 :  *      charsend            - converts char to binary format
     103                 :  */
     104                 : Datum
     105 UIC           0 : charsend(PG_FUNCTION_ARGS)
     106 EUB             : {
     107 UIC           0 :     char        arg1 = PG_GETARG_CHAR(0);
     108 EUB             :     StringInfoData buf;
     109                 : 
     110 UIC           0 :     pq_begintypsend(&buf);
     111 UBC           0 :     pq_sendbyte(&buf, arg1);
     112               0 :     PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
     113 EUB             : }
     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 GIC     2804213 : chareq(PG_FUNCTION_ARGS)
     128 ECB             : {
     129 GIC     2804213 :     char        arg1 = PG_GETARG_CHAR(0);
     130 CBC     2804213 :     char        arg2 = PG_GETARG_CHAR(1);
     131 ECB             : 
     132 GIC     2804213 :     PG_RETURN_BOOL(arg1 == arg2);
     133 ECB             : }
     134                 : 
     135                 : Datum
     136 GIC     1477017 : charne(PG_FUNCTION_ARGS)
     137 ECB             : {
     138 GIC     1477017 :     char        arg1 = PG_GETARG_CHAR(0);
     139 CBC     1477017 :     char        arg2 = PG_GETARG_CHAR(1);
     140 ECB             : 
     141 GIC     1477017 :     PG_RETURN_BOOL(arg1 != arg2);
     142 ECB             : }
     143                 : 
     144                 : Datum
     145 GIC        1548 : charlt(PG_FUNCTION_ARGS)
     146 ECB             : {
     147 GIC        1548 :     char        arg1 = PG_GETARG_CHAR(0);
     148 CBC        1548 :     char        arg2 = PG_GETARG_CHAR(1);
     149 ECB             : 
     150 GIC        1548 :     PG_RETURN_BOOL((uint8) arg1 < (uint8) arg2);
     151 ECB             : }
     152                 : 
     153                 : Datum
     154 GIC        1212 : charle(PG_FUNCTION_ARGS)
     155 ECB             : {
     156 GIC        1212 :     char        arg1 = PG_GETARG_CHAR(0);
     157 CBC        1212 :     char        arg2 = PG_GETARG_CHAR(1);
     158 ECB             : 
     159 GIC        1212 :     PG_RETURN_BOOL((uint8) arg1 <= (uint8) arg2);
     160 ECB             : }
     161                 : 
     162                 : Datum
     163 GIC        1521 : chargt(PG_FUNCTION_ARGS)
     164 ECB             : {
     165 GIC        1521 :     char        arg1 = PG_GETARG_CHAR(0);
     166 CBC        1521 :     char        arg2 = PG_GETARG_CHAR(1);
     167 ECB             : 
     168 GIC        1521 :     PG_RETURN_BOOL((uint8) arg1 > (uint8) arg2);
     169 ECB             : }
     170                 : 
     171                 : Datum
     172 GIC        1065 : charge(PG_FUNCTION_ARGS)
     173 ECB             : {
     174 GIC        1065 :     char        arg1 = PG_GETARG_CHAR(0);
     175 CBC        1065 :     char        arg2 = PG_GETARG_CHAR(1);
     176 ECB             : 
     177 GIC        1065 :     PG_RETURN_BOOL((uint8) arg1 >= (uint8) arg2);
     178 ECB             : }
     179                 : 
     180                 : 
     181                 : Datum
     182 UIC           0 : chartoi4(PG_FUNCTION_ARGS)
     183 EUB             : {
     184 UIC           0 :     char        arg1 = PG_GETARG_CHAR(0);
     185 EUB             : 
     186 UIC           0 :     PG_RETURN_INT32((int32) ((int8) arg1));
     187 EUB             : }
     188                 : 
     189                 : Datum
     190 UIC           0 : i4tochar(PG_FUNCTION_ARGS)
     191 EUB             : {
     192 UIC           0 :     int32       arg1 = PG_GETARG_INT32(0);
     193 EUB             : 
     194 UIC           0 :     if (arg1 < SCHAR_MIN || arg1 > SCHAR_MAX)
     195 UBC           0 :         ereport(ERROR,
     196 EUB             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     197                 :                  errmsg("\"char\" out of range")));
     198                 : 
     199 UIC           0 :     PG_RETURN_CHAR((int8) arg1);
     200 EUB             : }
     201                 : 
     202                 : 
     203                 : Datum
     204 GIC       38849 : text_char(PG_FUNCTION_ARGS)
     205 ECB             : {
     206 GIC       38849 :     text       *arg1 = PG_GETARG_TEXT_PP(0);
     207 CBC       38849 :     char       *ch = VARDATA_ANY(arg1);
     208 ECB             :     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 GIC       38849 :     if (VARSIZE_ANY_EXHDR(arg1) == 4 && ch[0] == '\\' &&
     215 CBC           3 :         ISOCTAL(ch[1]) && ISOCTAL(ch[2]) && ISOCTAL(ch[3]))
     216               3 :         result = (FROMOCTAL(ch[1]) << 6) +
     217               3 :             (FROMOCTAL(ch[2]) << 3) +
     218               3 :             FROMOCTAL(ch[3]);
     219           38846 :     else if (VARSIZE_ANY_EXHDR(arg1) > 0)
     220           38843 :         result = ch[0];
     221 ECB             :     else
     222 GIC           3 :         result = '\0';
     223 ECB             : 
     224 GIC       38849 :     PG_RETURN_CHAR(result);
     225 ECB             : }
     226                 : 
     227                 : Datum
     228 GIC       15422 : char_text(PG_FUNCTION_ARGS)
     229 ECB             : {
     230 GIC       15422 :     char        arg1 = PG_GETARG_CHAR(0);
     231 CBC       15422 :     text       *result = palloc(VARHDRSZ + 4);
     232 ECB             : 
     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 GIC       15422 :     if (IS_HIGHBIT_SET(arg1))
     238 ECB             :     {
     239 GIC           3 :         SET_VARSIZE(result, VARHDRSZ + 4);
     240 CBC           3 :         (VARDATA(result))[0] = '\\';
     241               3 :         (VARDATA(result))[1] = TOOCTAL(((unsigned char) arg1) >> 6);
     242               3 :         (VARDATA(result))[2] = TOOCTAL((((unsigned char) arg1) >> 3) & 07);
     243               3 :         (VARDATA(result))[3] = TOOCTAL(((unsigned char) arg1) & 07);
     244 ECB             :     }
     245 GIC       15419 :     else if (arg1 != '\0')
     246 ECB             :     {
     247 GIC       15416 :         SET_VARSIZE(result, VARHDRSZ + 1);
     248 CBC       15416 :         *(VARDATA(result)) = arg1;
     249 ECB             :     }
     250                 :     else
     251 GIC           3 :         SET_VARSIZE(result, VARHDRSZ);
     252 ECB             : 
     253 GIC       15422 :     PG_RETURN_TEXT_P(result);
     254 ECB             : }
        

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