LCOV - code coverage report
Current view: top level - src/backend/utils/adt - encode.c (source / functions) Hit Total Coverage
Test: PostgreSQL 18devel Lines: 199 224 88.8 %
Date: 2025-01-18 04:15:08 Functions: 17 17 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * encode.c
       4             :  *    Various data encoding/decoding things.
       5             :  *
       6             :  * Copyright (c) 2001-2025, PostgreSQL Global Development Group
       7             :  *
       8             :  *
       9             :  * IDENTIFICATION
      10             :  *    src/backend/utils/adt/encode.c
      11             :  *
      12             :  *-------------------------------------------------------------------------
      13             :  */
      14             : #include "postgres.h"
      15             : 
      16             : #include <ctype.h>
      17             : 
      18             : #include "mb/pg_wchar.h"
      19             : #include "utils/builtins.h"
      20             : #include "utils/memutils.h"
      21             : #include "varatt.h"
      22             : 
      23             : 
      24             : /*
      25             :  * Encoding conversion API.
      26             :  * encode_len() and decode_len() compute the amount of space needed, while
      27             :  * encode() and decode() perform the actual conversions.  It is okay for
      28             :  * the _len functions to return an overestimate, but not an underestimate.
      29             :  * (Having said that, large overestimates could cause unnecessary errors,
      30             :  * so it's better to get it right.)  The conversion routines write to the
      31             :  * buffer at *res and return the true length of their output.
      32             :  */
      33             : struct pg_encoding
      34             : {
      35             :     uint64      (*encode_len) (const char *data, size_t dlen);
      36             :     uint64      (*decode_len) (const char *data, size_t dlen);
      37             :     uint64      (*encode) (const char *data, size_t dlen, char *res);
      38             :     uint64      (*decode) (const char *data, size_t dlen, char *res);
      39             : };
      40             : 
      41             : static const struct pg_encoding *pg_find_encoding(const char *name);
      42             : 
      43             : /*
      44             :  * SQL functions.
      45             :  */
      46             : 
      47             : Datum
      48      485416 : binary_encode(PG_FUNCTION_ARGS)
      49             : {
      50      485416 :     bytea      *data = PG_GETARG_BYTEA_PP(0);
      51      485416 :     Datum       name = PG_GETARG_DATUM(1);
      52             :     text       *result;
      53             :     char       *namebuf;
      54             :     char       *dataptr;
      55             :     size_t      datalen;
      56             :     uint64      resultlen;
      57             :     uint64      res;
      58             :     const struct pg_encoding *enc;
      59             : 
      60      485416 :     namebuf = TextDatumGetCString(name);
      61             : 
      62      485416 :     enc = pg_find_encoding(namebuf);
      63      485416 :     if (enc == NULL)
      64           0 :         ereport(ERROR,
      65             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
      66             :                  errmsg("unrecognized encoding: \"%s\"", namebuf)));
      67             : 
      68      485416 :     dataptr = VARDATA_ANY(data);
      69      485416 :     datalen = VARSIZE_ANY_EXHDR(data);
      70             : 
      71      485416 :     resultlen = enc->encode_len(dataptr, datalen);
      72             : 
      73             :     /*
      74             :      * resultlen possibly overflows uint32, therefore on 32-bit machines it's
      75             :      * unsafe to rely on palloc's internal check.
      76             :      */
      77      485416 :     if (resultlen > MaxAllocSize - VARHDRSZ)
      78           0 :         ereport(ERROR,
      79             :                 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
      80             :                  errmsg("result of encoding conversion is too large")));
      81             : 
      82      485416 :     result = palloc(VARHDRSZ + resultlen);
      83             : 
      84      485416 :     res = enc->encode(dataptr, datalen, VARDATA(result));
      85             : 
      86             :     /* Make this FATAL 'cause we've trodden on memory ... */
      87      485416 :     if (res > resultlen)
      88           0 :         elog(FATAL, "overflow - encode estimate too small");
      89             : 
      90      485416 :     SET_VARSIZE(result, VARHDRSZ + res);
      91             : 
      92      485416 :     PG_RETURN_TEXT_P(result);
      93             : }
      94             : 
      95             : Datum
      96       32864 : binary_decode(PG_FUNCTION_ARGS)
      97             : {
      98       32864 :     text       *data = PG_GETARG_TEXT_PP(0);
      99       32864 :     Datum       name = PG_GETARG_DATUM(1);
     100             :     bytea      *result;
     101             :     char       *namebuf;
     102             :     char       *dataptr;
     103             :     size_t      datalen;
     104             :     uint64      resultlen;
     105             :     uint64      res;
     106             :     const struct pg_encoding *enc;
     107             : 
     108       32864 :     namebuf = TextDatumGetCString(name);
     109             : 
     110       32864 :     enc = pg_find_encoding(namebuf);
     111       32864 :     if (enc == NULL)
     112           0 :         ereport(ERROR,
     113             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     114             :                  errmsg("unrecognized encoding: \"%s\"", namebuf)));
     115             : 
     116       32864 :     dataptr = VARDATA_ANY(data);
     117       32864 :     datalen = VARSIZE_ANY_EXHDR(data);
     118             : 
     119       32864 :     resultlen = enc->decode_len(dataptr, datalen);
     120             : 
     121             :     /*
     122             :      * resultlen possibly overflows uint32, therefore on 32-bit machines it's
     123             :      * unsafe to rely on palloc's internal check.
     124             :      */
     125       32864 :     if (resultlen > MaxAllocSize - VARHDRSZ)
     126           0 :         ereport(ERROR,
     127             :                 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
     128             :                  errmsg("result of decoding conversion is too large")));
     129             : 
     130       32864 :     result = palloc(VARHDRSZ + resultlen);
     131             : 
     132       32864 :     res = enc->decode(dataptr, datalen, VARDATA(result));
     133             : 
     134             :     /* Make this FATAL 'cause we've trodden on memory ... */
     135       32864 :     if (res > resultlen)
     136           0 :         elog(FATAL, "overflow - decode estimate too small");
     137             : 
     138       32864 :     SET_VARSIZE(result, VARHDRSZ + res);
     139             : 
     140       32864 :     PG_RETURN_BYTEA_P(result);
     141             : }
     142             : 
     143             : 
     144             : /*
     145             :  * HEX
     146             :  */
     147             : 
     148             : /*
     149             :  * The hex expansion of each possible byte value (two chars per value).
     150             :  */
     151             : static const char hextbl[512] =
     152             : "000102030405060708090a0b0c0d0e0f"
     153             : "101112131415161718191a1b1c1d1e1f"
     154             : "202122232425262728292a2b2c2d2e2f"
     155             : "303132333435363738393a3b3c3d3e3f"
     156             : "404142434445464748494a4b4c4d4e4f"
     157             : "505152535455565758595a5b5c5d5e5f"
     158             : "606162636465666768696a6b6c6d6e6f"
     159             : "707172737475767778797a7b7c7d7e7f"
     160             : "808182838485868788898a8b8c8d8e8f"
     161             : "909192939495969798999a9b9c9d9e9f"
     162             : "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
     163             : "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
     164             : "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
     165             : "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
     166             : "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
     167             : "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";
     168             : 
     169             : static const int8 hexlookup[128] = {
     170             :     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     171             :     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     172             :     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     173             :     0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
     174             :     -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     175             :     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     176             :     -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     177             :     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     178             : };
     179             : 
     180             : uint64
     181      945138 : hex_encode(const char *src, size_t len, char *dst)
     182             : {
     183      945138 :     const char *end = src + len;
     184             : 
     185    23188806 :     while (src < end)
     186             :     {
     187    22243668 :         unsigned char usrc = *((const unsigned char *) src);
     188             : 
     189    22243668 :         memcpy(dst, &hextbl[2 * usrc], 2);
     190    22243668 :         src++;
     191    22243668 :         dst += 2;
     192             :     }
     193      945138 :     return (uint64) len * 2;
     194             : }
     195             : 
     196             : static inline bool
     197     7924530 : get_hex(const char *cp, char *out)
     198             : {
     199     7924530 :     unsigned char c = (unsigned char) *cp;
     200     7924530 :     int         res = -1;
     201             : 
     202     7924530 :     if (c < 127)
     203     7924530 :         res = hexlookup[c];
     204             : 
     205     7924530 :     *out = (char) res;
     206             : 
     207     7924530 :     return (res >= 0);
     208             : }
     209             : 
     210             : uint64
     211       32824 : hex_decode(const char *src, size_t len, char *dst)
     212             : {
     213       32824 :     return hex_decode_safe(src, len, dst, NULL);
     214             : }
     215             : 
     216             : uint64
     217      143956 : hex_decode_safe(const char *src, size_t len, char *dst, Node *escontext)
     218             : {
     219             :     const char *s,
     220             :                *srcend;
     221             :     char        v1,
     222             :                 v2,
     223             :                *p;
     224             : 
     225      143956 :     srcend = src + len;
     226      143956 :     s = src;
     227      143956 :     p = dst;
     228     4106260 :     while (s < srcend)
     229             :     {
     230     3962334 :         if (*s == ' ' || *s == '\n' || *s == '\t' || *s == '\r')
     231             :         {
     232          60 :             s++;
     233          60 :             continue;
     234             :         }
     235     3962274 :         if (!get_hex(s, &v1))
     236           0 :             ereturn(escontext, 0,
     237             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     238             :                      errmsg("invalid hexadecimal digit: \"%.*s\"",
     239             :                             pg_mblen(s), s)));
     240     3962274 :         s++;
     241     3962274 :         if (s >= srcend)
     242          18 :             ereturn(escontext, 0,
     243             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     244             :                      errmsg("invalid hexadecimal data: odd number of digits")));
     245     3962256 :         if (!get_hex(s, &v2))
     246          12 :             ereturn(escontext, 0,
     247             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     248             :                      errmsg("invalid hexadecimal digit: \"%.*s\"",
     249             :                             pg_mblen(s), s)));
     250     3962244 :         s++;
     251     3962244 :         *p++ = (v1 << 4) | v2;
     252             :     }
     253             : 
     254      143926 :     return p - dst;
     255             : }
     256             : 
     257             : static uint64
     258      485328 : hex_enc_len(const char *src, size_t srclen)
     259             : {
     260      485328 :     return (uint64) srclen << 1;
     261             : }
     262             : 
     263             : static uint64
     264       32824 : hex_dec_len(const char *src, size_t srclen)
     265             : {
     266       32824 :     return (uint64) srclen >> 1;
     267             : }
     268             : 
     269             : /*
     270             :  * BASE64
     271             :  */
     272             : 
     273             : static const char _base64[] =
     274             : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
     275             : 
     276             : static const int8 b64lookup[128] = {
     277             :     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     278             :     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     279             :     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
     280             :     52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
     281             :     -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
     282             :     15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
     283             :     -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
     284             :     41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
     285             : };
     286             : 
     287             : static uint64
     288          12 : pg_base64_encode(const char *src, size_t len, char *dst)
     289             : {
     290             :     char       *p,
     291          12 :                *lend = dst + 76;
     292             :     const char *s,
     293          12 :                *end = src + len;
     294          12 :     int         pos = 2;
     295          12 :     uint32      buf = 0;
     296             : 
     297          12 :     s = src;
     298          12 :     p = dst;
     299             : 
     300         852 :     while (s < end)
     301             :     {
     302         840 :         buf |= (unsigned char) *s << (pos << 3);
     303         840 :         pos--;
     304         840 :         s++;
     305             : 
     306             :         /* write it out */
     307         840 :         if (pos < 0)
     308             :         {
     309         276 :             *p++ = _base64[(buf >> 18) & 0x3f];
     310         276 :             *p++ = _base64[(buf >> 12) & 0x3f];
     311         276 :             *p++ = _base64[(buf >> 6) & 0x3f];
     312         276 :             *p++ = _base64[buf & 0x3f];
     313             : 
     314         276 :             pos = 2;
     315         276 :             buf = 0;
     316             :         }
     317         840 :         if (p >= lend)
     318             :         {
     319          12 :             *p++ = '\n';
     320          12 :             lend = p + 76;
     321             :         }
     322             :     }
     323          12 :     if (pos != 2)
     324             :     {
     325          12 :         *p++ = _base64[(buf >> 18) & 0x3f];
     326          12 :         *p++ = _base64[(buf >> 12) & 0x3f];
     327          12 :         *p++ = (pos == 0) ? _base64[(buf >> 6) & 0x3f] : '=';
     328          12 :         *p++ = '=';
     329             :     }
     330             : 
     331          12 :     return p - dst;
     332             : }
     333             : 
     334             : static uint64
     335          10 : pg_base64_decode(const char *src, size_t len, char *dst)
     336             : {
     337          10 :     const char *srcend = src + len,
     338          10 :                *s = src;
     339          10 :     char       *p = dst;
     340             :     char        c;
     341          10 :     int         b = 0;
     342          10 :     uint32      buf = 0;
     343          10 :     int         pos = 0,
     344          10 :                 end = 0;
     345             : 
     346         624 :     while (s < srcend)
     347             :     {
     348         614 :         c = *s++;
     349             : 
     350         614 :         if (c == ' ' || c == '\t' || c == '\n' || c == '\r')
     351           6 :             continue;
     352             : 
     353         608 :         if (c == '=')
     354             :         {
     355             :             /* end sequence */
     356          16 :             if (!end)
     357             :             {
     358          10 :                 if (pos == 2)
     359           6 :                     end = 1;
     360           4 :                 else if (pos == 3)
     361           4 :                     end = 2;
     362             :                 else
     363           0 :                     ereport(ERROR,
     364             :                             (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     365             :                              errmsg("unexpected \"=\" while decoding base64 sequence")));
     366             :             }
     367          16 :             b = 0;
     368             :         }
     369             :         else
     370             :         {
     371         592 :             b = -1;
     372         592 :             if (c > 0 && c < 127)
     373         592 :                 b = b64lookup[(unsigned char) c];
     374         592 :             if (b < 0)
     375           0 :                 ereport(ERROR,
     376             :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     377             :                          errmsg("invalid symbol \"%.*s\" found while decoding base64 sequence",
     378             :                                 pg_mblen(s - 1), s - 1)));
     379             :         }
     380             :         /* add it to buffer */
     381         608 :         buf = (buf << 6) + b;
     382         608 :         pos++;
     383         608 :         if (pos == 4)
     384             :         {
     385         152 :             *p++ = (buf >> 16) & 255;
     386         152 :             if (end == 0 || end > 1)
     387         146 :                 *p++ = (buf >> 8) & 255;
     388         152 :             if (end == 0 || end > 2)
     389         142 :                 *p++ = buf & 255;
     390         152 :             buf = 0;
     391         152 :             pos = 0;
     392             :         }
     393             :     }
     394             : 
     395          10 :     if (pos != 0)
     396           0 :         ereport(ERROR,
     397             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     398             :                  errmsg("invalid base64 end sequence"),
     399             :                  errhint("Input data is missing padding, is truncated, or is otherwise corrupted.")));
     400             : 
     401          10 :     return p - dst;
     402             : }
     403             : 
     404             : 
     405             : static uint64
     406          12 : pg_base64_enc_len(const char *src, size_t srclen)
     407             : {
     408             :     /* 3 bytes will be converted to 4, linefeed after 76 chars */
     409          12 :     return ((uint64) srclen + 2) / 3 * 4 + (uint64) srclen / (76 * 3 / 4);
     410             : }
     411             : 
     412             : static uint64
     413          10 : pg_base64_dec_len(const char *src, size_t srclen)
     414             : {
     415          10 :     return ((uint64) srclen * 3) >> 2;
     416             : }
     417             : 
     418             : /*
     419             :  * Escape
     420             :  * Minimally escape bytea to text.
     421             :  * De-escape text to bytea.
     422             :  *
     423             :  * We must escape zero bytes and high-bit-set bytes to avoid generating
     424             :  * text that might be invalid in the current encoding, or that might
     425             :  * change to something else if passed through an encoding conversion
     426             :  * (leading to failing to de-escape to the original bytea value).
     427             :  * Also of course backslash itself has to be escaped.
     428             :  *
     429             :  * De-escaping processes \\ and any \### octal
     430             :  */
     431             : 
     432             : #define VAL(CH)         ((CH) - '0')
     433             : #define DIG(VAL)        ((VAL) + '0')
     434             : 
     435             : static uint64
     436          76 : esc_encode(const char *src, size_t srclen, char *dst)
     437             : {
     438          76 :     const char *end = src + srclen;
     439          76 :     char       *rp = dst;
     440          76 :     uint64      len = 0;
     441             : 
     442         732 :     while (src < end)
     443             :     {
     444         656 :         unsigned char c = (unsigned char) *src;
     445             : 
     446         656 :         if (c == '\0' || IS_HIGHBIT_SET(c))
     447             :         {
     448          82 :             rp[0] = '\\';
     449          82 :             rp[1] = DIG(c >> 6);
     450          82 :             rp[2] = DIG((c >> 3) & 7);
     451          82 :             rp[3] = DIG(c & 7);
     452          82 :             rp += 4;
     453          82 :             len += 4;
     454             :         }
     455         574 :         else if (c == '\\')
     456             :         {
     457           0 :             rp[0] = '\\';
     458           0 :             rp[1] = '\\';
     459           0 :             rp += 2;
     460           0 :             len += 2;
     461             :         }
     462             :         else
     463             :         {
     464         574 :             *rp++ = c;
     465         574 :             len++;
     466             :         }
     467             : 
     468         656 :         src++;
     469             :     }
     470             : 
     471          76 :     return len;
     472             : }
     473             : 
     474             : static uint64
     475          30 : esc_decode(const char *src, size_t srclen, char *dst)
     476             : {
     477          30 :     const char *end = src + srclen;
     478          30 :     char       *rp = dst;
     479          30 :     uint64      len = 0;
     480             : 
     481     2400084 :     while (src < end)
     482             :     {
     483     2400054 :         if (src[0] != '\\')
     484     2400024 :             *rp++ = *src++;
     485          30 :         else if (src + 3 < end &&
     486          30 :                  (src[1] >= '0' && src[1] <= '3') &&
     487          30 :                  (src[2] >= '0' && src[2] <= '7') &&
     488          30 :                  (src[3] >= '0' && src[3] <= '7'))
     489          30 :         {
     490             :             int         val;
     491             : 
     492          30 :             val = VAL(src[1]);
     493          30 :             val <<= 3;
     494          30 :             val += VAL(src[2]);
     495          30 :             val <<= 3;
     496          30 :             *rp++ = val + VAL(src[3]);
     497          30 :             src += 4;
     498             :         }
     499           0 :         else if (src + 1 < end &&
     500           0 :                  (src[1] == '\\'))
     501             :         {
     502           0 :             *rp++ = '\\';
     503           0 :             src += 2;
     504             :         }
     505             :         else
     506             :         {
     507             :             /*
     508             :              * One backslash, not followed by ### valid octal. Should never
     509             :              * get here, since esc_dec_len does same check.
     510             :              */
     511           0 :             ereport(ERROR,
     512             :                     (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
     513             :                      errmsg("invalid input syntax for type %s", "bytea")));
     514             :         }
     515             : 
     516     2400054 :         len++;
     517             :     }
     518             : 
     519          30 :     return len;
     520             : }
     521             : 
     522             : static uint64
     523          76 : esc_enc_len(const char *src, size_t srclen)
     524             : {
     525          76 :     const char *end = src + srclen;
     526          76 :     uint64      len = 0;
     527             : 
     528         732 :     while (src < end)
     529             :     {
     530         656 :         if (*src == '\0' || IS_HIGHBIT_SET(*src))
     531          82 :             len += 4;
     532         574 :         else if (*src == '\\')
     533           0 :             len += 2;
     534             :         else
     535         574 :             len++;
     536             : 
     537         656 :         src++;
     538             :     }
     539             : 
     540          76 :     return len;
     541             : }
     542             : 
     543             : static uint64
     544          30 : esc_dec_len(const char *src, size_t srclen)
     545             : {
     546          30 :     const char *end = src + srclen;
     547          30 :     uint64      len = 0;
     548             : 
     549     2400084 :     while (src < end)
     550             :     {
     551     2400054 :         if (src[0] != '\\')
     552     2400024 :             src++;
     553          30 :         else if (src + 3 < end &&
     554          30 :                  (src[1] >= '0' && src[1] <= '3') &&
     555          30 :                  (src[2] >= '0' && src[2] <= '7') &&
     556          30 :                  (src[3] >= '0' && src[3] <= '7'))
     557             :         {
     558             :             /*
     559             :              * backslash + valid octal
     560             :              */
     561          30 :             src += 4;
     562             :         }
     563           0 :         else if (src + 1 < end &&
     564           0 :                  (src[1] == '\\'))
     565             :         {
     566             :             /*
     567             :              * two backslashes = backslash
     568             :              */
     569           0 :             src += 2;
     570             :         }
     571             :         else
     572             :         {
     573             :             /*
     574             :              * one backslash, not followed by ### valid octal
     575             :              */
     576           0 :             ereport(ERROR,
     577             :                     (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
     578             :                      errmsg("invalid input syntax for type %s", "bytea")));
     579             :         }
     580             : 
     581     2400054 :         len++;
     582             :     }
     583          30 :     return len;
     584             : }
     585             : 
     586             : /*
     587             :  * Common
     588             :  */
     589             : 
     590             : static const struct
     591             : {
     592             :     const char *name;
     593             :     struct pg_encoding enc;
     594             : }           enclist[] =
     595             : 
     596             : {
     597             :     {
     598             :         "hex",
     599             :         {
     600             :             hex_enc_len, hex_dec_len, hex_encode, hex_decode
     601             :         }
     602             :     },
     603             :     {
     604             :         "base64",
     605             :         {
     606             :             pg_base64_enc_len, pg_base64_dec_len, pg_base64_encode, pg_base64_decode
     607             :         }
     608             :     },
     609             :     {
     610             :         "escape",
     611             :         {
     612             :             esc_enc_len, esc_dec_len, esc_encode, esc_decode
     613             :         }
     614             :     },
     615             :     {
     616             :         NULL,
     617             :         {
     618             :             NULL, NULL, NULL, NULL
     619             :         }
     620             :     }
     621             : };
     622             : 
     623             : static const struct pg_encoding *
     624      518280 : pg_find_encoding(const char *name)
     625             : {
     626             :     int         i;
     627             : 
     628      518514 :     for (i = 0; enclist[i].name; i++)
     629      518514 :         if (pg_strcasecmp(enclist[i].name, name) == 0)
     630      518280 :             return &enclist[i].enc;
     631             : 
     632           0 :     return NULL;
     633             : }

Generated by: LCOV version 1.14