diff options
Diffstat (limited to 'src/backend/utils/adt/encode.c')
-rw-r--r-- | src/backend/utils/adt/encode.c | 537 |
1 files changed, 0 insertions, 537 deletions
diff --git a/src/backend/utils/adt/encode.c b/src/backend/utils/adt/encode.c deleted file mode 100644 index 21139b89f4f..00000000000 --- a/src/backend/utils/adt/encode.c +++ /dev/null @@ -1,537 +0,0 @@ -/*------------------------------------------------------------------------- - * - * encode.c - * Various data encoding/decoding things. - * - * Copyright (c) 2001 PostgreSQL Global Development Group - * - * - * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/encode.c,v 1.6 2001/11/05 17:46:29 momjian Exp $ - * - *------------------------------------------------------------------------- - */ -#include "postgres.h" - -#include <ctype.h> - -#include "utils/builtins.h" - - -struct pg_encoding -{ - unsigned (*encode_len) (const uint8 *data, unsigned dlen); - unsigned (*decode_len) (const uint8 *data, unsigned dlen); - unsigned (*encode) (const uint8 *data, unsigned dlen, uint8 *res); - unsigned (*decode) (const uint8 *data, unsigned dlen, uint8 *res); -}; - -static struct pg_encoding *pg_find_encoding(const char *name); - -/* - * SQL functions. - */ - -Datum -binary_encode(PG_FUNCTION_ARGS) -{ - bytea *data = PG_GETARG_BYTEA_P(0); - Datum name = PG_GETARG_DATUM(1); - text *result; - char *namebuf; - int datalen, - resultlen, - res; - struct pg_encoding *enc; - - datalen = VARSIZE(data) - VARHDRSZ; - - namebuf = DatumGetCString(DirectFunctionCall1(textout, name)); - - enc = pg_find_encoding(namebuf); - if (enc == NULL) - elog(ERROR, "No such encoding as '%s'", namebuf); - - resultlen = enc->encode_len(VARDATA(data), datalen); - result = palloc(VARHDRSZ + resultlen); - - res = enc->encode(VARDATA(data), datalen, VARDATA(result)); - - /* Make this FATAL 'cause we've trodden on memory ... */ - if (res > resultlen) - elog(FATAL, "Overflow - encode estimate too small"); - - VARATT_SIZEP(result) = VARHDRSZ + res; - - PG_RETURN_TEXT_P(result); -} - -Datum -binary_decode(PG_FUNCTION_ARGS) -{ - text *data = PG_GETARG_TEXT_P(0); - Datum name = PG_GETARG_DATUM(1); - bytea *result; - char *namebuf; - int datalen, - resultlen, - res; - struct pg_encoding *enc; - - datalen = VARSIZE(data) - VARHDRSZ; - - namebuf = DatumGetCString(DirectFunctionCall1(textout, name)); - - enc = pg_find_encoding(namebuf); - if (enc == NULL) - elog(ERROR, "No such encoding as '%s'", namebuf); - - resultlen = enc->decode_len(VARDATA(data), datalen); - result = palloc(VARHDRSZ + resultlen); - - res = enc->decode(VARDATA(data), datalen, VARDATA(result)); - - /* Make this FATAL 'cause we've trodden on memory ... */ - if (res > resultlen) - elog(FATAL, "Overflow - decode estimate too small"); - - VARATT_SIZEP(result) = VARHDRSZ + res; - - PG_RETURN_BYTEA_P(result); -} - - -/* - * HEX - */ - -static const char *hextbl = "0123456789abcdef"; - -static const int8 hexlookup[128] = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, - -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -}; - -static unsigned -hex_encode(const uint8 *src, unsigned len, uint8 *dst) -{ - const uint8 *end = src + len; - - while (src < end) - { - *dst++ = hextbl[(*src >> 4) & 0xF]; - *dst++ = hextbl[*src & 0xF]; - src++; - } - return len * 2; -} - -static uint8 -get_hex(unsigned c) -{ - int res = -1; - - if (c > 0 && c < 127) - res = hexlookup[c]; - - if (res < 0) - elog(ERROR, "Bad hex code: '%c'", c); - - return (uint8) res; -} - -static unsigned -hex_decode(const uint8 *src, unsigned len, uint8 *dst) -{ - const uint8 *s, - *srcend; - uint8 v1, - v2, - *p = dst; - - srcend = src + len; - s = src; - p = dst; - while (s < srcend) - { - if (*s == ' ' || *s == '\n' || *s == '\t' || *s == '\r') - { - s++; - continue; - } - v1 = get_hex(*s++) << 4; - if (s >= srcend) - elog(ERROR, "hex_decode: invalid data"); - v2 = get_hex(*s++); - *p++ = v1 | v2; - } - - return p - dst; -} - -static unsigned -hex_enc_len(const uint8 *src, unsigned srclen) -{ - return srclen << 1; -} - -static unsigned -hex_dec_len(const uint8 *src, unsigned srclen) -{ - return srclen >> 1; -} - -/* - * BASE64 - */ - -static const unsigned char _base64[] = -"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -static const int8 b64lookup[128] = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, - -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, - -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, -}; - -static unsigned -b64_encode(const uint8 *src, unsigned len, uint8 *dst) -{ - uint8 *p, - *lend = dst + 76; - const uint8 *s, - *end = src + len; - int pos = 2; - uint32 buf = 0; - - s = src; - p = dst; - - while (s < end) - { - buf |= *s << (pos << 3); - pos--; - s++; - - /* write it out */ - if (pos < 0) - { - *p++ = _base64[(buf >> 18) & 0x3f]; - *p++ = _base64[(buf >> 12) & 0x3f]; - *p++ = _base64[(buf >> 6) & 0x3f]; - *p++ = _base64[buf & 0x3f]; - - pos = 2; - buf = 0; - } - if (p >= lend) - { - *p++ = '\n'; - lend = p + 76; - } - } - if (pos != 2) - { - *p++ = _base64[(buf >> 18) & 0x3f]; - *p++ = _base64[(buf >> 12) & 0x3f]; - *p++ = (pos == 0) ? _base64[(buf >> 6) & 0x3f] : '='; - *p++ = '='; - } - - return p - dst; -} - -static unsigned -b64_decode(const uint8 *src, unsigned len, uint8 *dst) -{ - const char *srcend = src + len, - *s = src; - uint8 *p = dst; - unsigned c; - int b = 0; - uint32 buf = 0; - int pos = 0, - end = 0; - - while (s < srcend) - { - c = *s++; - - if (c == ' ' || c == '\t' || c == '\n' || c == '\r') - continue; - - if (c == '=') - { - /* end sequence */ - if (!end) - { - if (pos == 2) - end = 1; - else if (pos == 3) - end = 2; - else - elog(ERROR, "base64: unexpected '='"); - } - b = 0; - } - else - { - b = -1; - if (c > 0 && c < 127) - b = b64lookup[c]; - if (b < 0) - elog(ERROR, "base64: Invalid symbol"); - } - /* add it to buffer */ - buf = (buf << 6) + b; - pos++; - if (pos == 4) - { - *p++ = (buf >> 16) & 255; - if (end == 0 || end > 1) - *p++ = (buf >> 8) & 255; - if (end == 0 || end > 2) - *p++ = buf & 255; - buf = 0; - pos = 0; - } - } - - if (pos != 0) - elog(ERROR, "base64: invalid end sequence"); - - return p - dst; -} - - -static unsigned -b64_enc_len(const uint8 *src, unsigned srclen) -{ - /* 3 bytes will be converted to 4, linefeed after 76 chars */ - return (srclen + 2) * 4 / 3 + srclen / (76 * 3 / 4); -} - -static unsigned -b64_dec_len(const uint8 *src, unsigned srclen) -{ - return (srclen * 3) >> 2; -} - -/* - * Escape - * Minimally escape bytea to text. - * De-escape text to bytea. - * - * Only two characters are escaped: - * \0 (null) and \\ (backslash) - * - * De-escapes \\ and any \### octal - */ - -#define VAL(CH) ((CH) - '0') -#define DIG(VAL) ((VAL) + '0') - -static unsigned -esc_encode(const uint8 *src, unsigned srclen, uint8 *dst) -{ - const uint8 *end = src + srclen; - uint8 *rp = dst; - int len = 0; - - while (src < end) - { - if (*src == '\0') - { - rp[0] = '\\'; - rp[1] = '0'; - rp[2] = '0'; - rp[3] = '0'; - rp += 4; - len += 4; - } - else if (*src == '\\') - { - rp[0] = '\\'; - rp[1] = '\\'; - rp += 2; - len += 2; - } - else - { - *rp++ = *src; - len++; - } - - src++; - } - - return len; -} - -static unsigned -esc_decode(const uint8 *src, unsigned srclen, uint8 *dst) -{ - const uint8 *end = src + srclen; - uint8 *rp = dst; - int len = 0; - - while (src < end) - { - if (src[0] != '\\') - *rp++ = *src++; - else if (src + 3 < end && - (src[1] >= '0' && src[1] <= '3') && - (src[2] >= '0' && src[2] <= '7') && - (src[3] >= '0' && src[3] <= '7')) - { - int val; - - val = VAL(src[1]); - val <<= 3; - val += VAL(src[2]); - val <<= 3; - *rp++ = val + VAL(src[3]); - src += 4; - } - else if (src + 1 < end && - (src[1] == '\\')) - { - *rp++ = '\\'; - src += 2; - } - else - { - /* - * One backslash, not followed by ### valid octal. Should - * never get here, since esc_dec_len does same check. - */ - elog(ERROR, "decode: Bad input string for type bytea"); - } - - len++; - } - - return len; -} - -static unsigned -esc_enc_len(const uint8 *src, unsigned srclen) -{ - const uint8 *end = src + srclen; - int len = 0; - - while (src < end) - { - if (*src == '\0') - len += 4; - else if (*src == '\\') - len += 2; - else - len++; - - src++; - } - - return len; -} - -static unsigned -esc_dec_len(const uint8 *src, unsigned srclen) -{ - const uint8 *end = src + srclen; - int len = 0; - - while (src < end) - { - if (src[0] != '\\') - src++; - else if (src + 3 < end && - (src[1] >= '0' && src[1] <= '3') && - (src[2] >= '0' && src[2] <= '7') && - (src[3] >= '0' && src[3] <= '7')) - { - /* - * backslash + valid octal - */ - src += 4; - } - else if (src + 1 < end && - (src[1] == '\\')) - { - /* - * two backslashes = backslash - */ - src += 2; - } - else - { - /* - * one backslash, not followed by ### valid octal - */ - elog(ERROR, "decode: Bad input string for type bytea"); - } - - len++; - } - return len; -} - -/* - * Common - */ - -static struct -{ - const char *name; - struct pg_encoding enc; -} enclist[] = - -{ - { - "hex", - { - hex_enc_len, hex_dec_len, hex_encode, hex_decode - } - }, - { - "base64", - { - b64_enc_len, b64_dec_len, b64_encode, b64_decode - } - }, - { - "escape", - { - esc_enc_len, esc_dec_len, esc_encode, esc_decode - } - }, - { - NULL, - { - NULL, NULL, NULL, NULL - } - } -}; - -static struct pg_encoding * -pg_find_encoding(const char *name) -{ - int i; - - for (i = 0; enclist[i].name; i++) - if (strcasecmp(enclist[i].name, name) == 0) - return &enclist[i].enc; - - return NULL; -} |