0004-Move-encoding-routines-to-src-common.patch
application/x-patch
Filename: 0004-Move-encoding-routines-to-src-common.patch
Type: application/x-patch
Part: 0
Patch
Format: format-patch
Series: patch 0004
Subject: Move encoding routines to src/common/
| File | + | − |
|---|---|---|
| src/backend/utils/adt/encode.c | 1 | 407 |
| src/backend/utils/adt/varlena.c | 1 | 0 |
| src/common/encode.c | 132 | 224 |
| src/common/Makefile | 3 | 3 |
| src/include/common/encode.h | 30 | 0 |
| src/include/utils/builtins.h | 0 | 2 |
| src/tools/msvc/Mkvcbuild.pm | 1 | 1 |
From 5e2d6423e372a1b4b5e6e93b12482a7faac1b37e Mon Sep 17 00:00:00 2001
From: Michael Paquier <michael@otacoo.com>
Date: Mon, 25 Jul 2016 13:35:26 +0900
Subject: [PATCH 04/10] Move encoding routines to src/common/
The following encoding routines are moved for decode and encode:
- escape
- base64
- hex
base64 is planned to be used by SCRAM-SHA1, moving the others makes sense
for consistency.
---
src/backend/utils/adt/encode.c | 408 +----------------------------
src/backend/utils/adt/varlena.c | 1 +
src/common/Makefile | 6 +-
src/{backend/utils/adt => common}/encode.c | 356 ++++++++++---------------
src/include/common/encode.h | 30 +++
src/include/utils/builtins.h | 2 -
src/tools/msvc/Mkvcbuild.pm | 2 +-
7 files changed, 168 insertions(+), 637 deletions(-)
copy src/{backend/utils/adt => common}/encode.c (72%)
create mode 100644 src/include/common/encode.h
diff --git a/src/backend/utils/adt/encode.c b/src/backend/utils/adt/encode.c
index d833efc..76747bf 100644
--- a/src/backend/utils/adt/encode.c
+++ b/src/backend/utils/adt/encode.c
@@ -15,6 +15,7 @@
#include <ctype.h>
+#include "common/encode.h"
#include "utils/builtins.h"
@@ -106,413 +107,6 @@ binary_decode(PG_FUNCTION_ARGS)
/*
- * 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,
-};
-
-unsigned
-hex_encode(const char *src, unsigned len, char *dst)
-{
- const char *end = src + len;
-
- while (src < end)
- {
- *dst++ = hextbl[(*src >> 4) & 0xF];
- *dst++ = hextbl[*src & 0xF];
- src++;
- }
- return len * 2;
-}
-
-static inline char
-get_hex(char c)
-{
- int res = -1;
-
- if (c > 0 && c < 127)
- res = hexlookup[(unsigned char) c];
-
- if (res < 0)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("invalid hexadecimal digit: \"%c\"", c)));
-
- return (char) res;
-}
-
-unsigned
-hex_decode(const char *src, unsigned len, char *dst)
-{
- const char *s,
- *srcend;
- char v1,
- v2,
- *p;
-
- 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)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("invalid hexadecimal data: odd number of digits")));
-
- v2 = get_hex(*s++);
- *p++ = v1 | v2;
- }
-
- return p - dst;
-}
-
-static unsigned
-hex_enc_len(const char *src, unsigned srclen)
-{
- return srclen << 1;
-}
-
-static unsigned
-hex_dec_len(const char *src, unsigned srclen)
-{
- return srclen >> 1;
-}
-
-/*
- * BASE64
- */
-
-static const 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 char *src, unsigned len, char *dst)
-{
- char *p,
- *lend = dst + 76;
- const char *s,
- *end = src + len;
- int pos = 2;
- uint32 buf = 0;
-
- s = src;
- p = dst;
-
- while (s < end)
- {
- buf |= (unsigned char) *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 char *src, unsigned len, char *dst)
-{
- const char *srcend = src + len,
- *s = src;
- char *p = dst;
- char 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
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("unexpected \"=\" while decoding base64 sequence")));
- }
- b = 0;
- }
- else
- {
- b = -1;
- if (c > 0 && c < 127)
- b = b64lookup[(unsigned char) c];
- if (b < 0)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("invalid symbol \"%c\" while decoding base64 sequence", (int) c)));
- }
- /* 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)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("invalid base64 end sequence"),
- errhint("Input data is missing padding, is truncated, or is otherwise corrupted.")));
-
- return p - dst;
-}
-
-
-static unsigned
-b64_enc_len(const char *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 char *src, unsigned srclen)
-{
- return (srclen * 3) >> 2;
-}
-
-/*
- * Escape
- * Minimally escape bytea to text.
- * De-escape text to bytea.
- *
- * We must escape zero bytes and high-bit-set bytes to avoid generating
- * text that might be invalid in the current encoding, or that might
- * change to something else if passed through an encoding conversion
- * (leading to failing to de-escape to the original bytea value).
- * Also of course backslash itself has to be escaped.
- *
- * De-escaping processes \\ and any \### octal
- */
-
-#define VAL(CH) ((CH) - '0')
-#define DIG(VAL) ((VAL) + '0')
-
-static unsigned
-esc_encode(const char *src, unsigned srclen, char *dst)
-{
- const char *end = src + srclen;
- char *rp = dst;
- int len = 0;
-
- while (src < end)
- {
- unsigned char c = (unsigned char) *src;
-
- if (c == '\0' || IS_HIGHBIT_SET(c))
- {
- rp[0] = '\\';
- rp[1] = DIG(c >> 6);
- rp[2] = DIG((c >> 3) & 7);
- rp[3] = DIG(c & 7);
- rp += 4;
- len += 4;
- }
- else if (c == '\\')
- {
- rp[0] = '\\';
- rp[1] = '\\';
- rp += 2;
- len += 2;
- }
- else
- {
- *rp++ = c;
- len++;
- }
-
- src++;
- }
-
- return len;
-}
-
-static unsigned
-esc_decode(const char *src, unsigned srclen, char *dst)
-{
- const char *end = src + srclen;
- char *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.
- */
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("invalid input syntax for type bytea")));
- }
-
- len++;
- }
-
- return len;
-}
-
-static unsigned
-esc_enc_len(const char *src, unsigned srclen)
-{
- const char *end = src + srclen;
- int len = 0;
-
- while (src < end)
- {
- if (*src == '\0' || IS_HIGHBIT_SET(*src))
- len += 4;
- else if (*src == '\\')
- len += 2;
- else
- len++;
-
- src++;
- }
-
- return len;
-}
-
-static unsigned
-esc_dec_len(const char *src, unsigned srclen)
-{
- const char *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
- */
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("invalid input syntax for type bytea")));
- }
-
- len++;
- }
- return len;
-}
-
-/*
* Common
*/
diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c
index a869e85..6fec1f7 100644
--- a/src/backend/utils/adt/varlena.c
+++ b/src/backend/utils/adt/varlena.c
@@ -21,6 +21,7 @@
#include "access/tuptoaster.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_type.h"
+#include "common/encode.h"
#include "lib/hyperloglog.h"
#include "libpq/md5.h"
#include "libpq/pqformat.h"
diff --git a/src/common/Makefile b/src/common/Makefile
index c27e25e..186fcd0 100644
--- a/src/common/Makefile
+++ b/src/common/Makefile
@@ -36,9 +36,9 @@ override CPPFLAGS += -DVAL_LDFLAGS_EX="\"$(LDFLAGS_EX)\""
override CPPFLAGS += -DVAL_LDFLAGS_SL="\"$(LDFLAGS_SL)\""
override CPPFLAGS += -DVAL_LIBS="\"$(LIBS)\""
-OBJS_COMMON = config_info.o controldata_utils.o exec.o keywords.o \
- pg_lzcompress.o pgfnames.o psprintf.o relpath.o rmtree.o \
- string.o username.o wait_error.o
+OBJS_COMMON = config_info.o controldata_utils.o encode.o exec.o \
+ keywords.o pg_lzcompress.o pgfnames.o psprintf.o relpath.o \
+ rmtree.o string.o username.o wait_error.o
ifeq ($(with_openssl),yes)
OBJS_COMMON += sha_openssl.o
diff --git a/src/backend/utils/adt/encode.c b/src/common/encode.c
similarity index 72%
copy from src/backend/utils/adt/encode.c
copy to src/common/encode.c
index d833efc..4a07089 100644
--- a/src/backend/utils/adt/encode.c
+++ b/src/common/encode.c
@@ -1,200 +1,27 @@
/*-------------------------------------------------------------------------
*
* encode.c
- * Various data encoding/decoding things.
+ * Various data encoding/decoding things for base64, hexadecimal and
+ * escape. In case of failure, those routines return elog(ERROR) in
+ * the backend, and 0 in the frontend to let the caller handle the \
+ * error handling, something needed by libpq.
*
* Copyright (c) 2001-2016, PostgreSQL Global Development Group
*
*
* IDENTIFICATION
- * src/backend/utils/adt/encode.c
+ * src/common/encode.c
*
*-------------------------------------------------------------------------
*/
-#include "postgres.h"
-
-#include <ctype.h>
-
-#include "utils/builtins.h"
-
-
-struct pg_encoding
-{
- unsigned (*encode_len) (const char *data, unsigned dlen);
- unsigned (*decode_len) (const char *data, unsigned dlen);
- unsigned (*encode) (const char *data, unsigned dlen, char *res);
- unsigned (*decode) (const char *data, unsigned dlen, char *res);
-};
-
-static const 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;
- const struct pg_encoding *enc;
-
- datalen = VARSIZE(data) - VARHDRSZ;
-
- namebuf = TextDatumGetCString(name);
-
- enc = pg_find_encoding(namebuf);
- if (enc == NULL)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("unrecognized encoding: \"%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");
-
- SET_VARSIZE(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;
- const struct pg_encoding *enc;
-
- datalen = VARSIZE(data) - VARHDRSZ;
-
- namebuf = TextDatumGetCString(name);
-
- enc = pg_find_encoding(namebuf);
- if (enc == NULL)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("unrecognized encoding: \"%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");
-
- SET_VARSIZE(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,
-};
-
-unsigned
-hex_encode(const char *src, unsigned len, char *dst)
-{
- const char *end = src + len;
-
- while (src < end)
- {
- *dst++ = hextbl[(*src >> 4) & 0xF];
- *dst++ = hextbl[*src & 0xF];
- src++;
- }
- return len * 2;
-}
-
-static inline char
-get_hex(char c)
-{
- int res = -1;
-
- if (c > 0 && c < 127)
- res = hexlookup[(unsigned char) c];
-
- if (res < 0)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("invalid hexadecimal digit: \"%c\"", c)));
-
- return (char) res;
-}
-
-unsigned
-hex_decode(const char *src, unsigned len, char *dst)
-{
- const char *s,
- *srcend;
- char v1,
- v2,
- *p;
-
- 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)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("invalid hexadecimal data: odd number of digits")));
- v2 = get_hex(*s++);
- *p++ = v1 | v2;
- }
-
- return p - dst;
-}
-
-static unsigned
-hex_enc_len(const char *src, unsigned srclen)
-{
- return srclen << 1;
-}
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
-static unsigned
-hex_dec_len(const char *src, unsigned srclen)
-{
- return srclen >> 1;
-}
+#include "common/encode.h"
/*
* BASE64
@@ -214,7 +41,7 @@ static const int8 b64lookup[128] = {
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
};
-static unsigned
+unsigned
b64_encode(const char *src, unsigned len, char *dst)
{
char *p,
@@ -261,7 +88,7 @@ b64_encode(const char *src, unsigned len, char *dst)
return p - dst;
}
-static unsigned
+unsigned
b64_decode(const char *src, unsigned len, char *dst)
{
const char *srcend = src + len,
@@ -290,9 +117,15 @@ b64_decode(const char *src, unsigned len, char *dst)
else if (pos == 3)
end = 2;
else
+ {
+#ifndef FRONTEND
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("unexpected \"=\" while decoding base64 sequence")));
+#else
+ return 0;
+#endif
+ }
}
b = 0;
}
@@ -302,9 +135,16 @@ b64_decode(const char *src, unsigned len, char *dst)
if (c > 0 && c < 127)
b = b64lookup[(unsigned char) c];
if (b < 0)
+ {
+#ifndef FRONTEND
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("invalid symbol \"%c\" while decoding base64 sequence", (int) c)));
+ errmsg("invalid symbol \"%c\" while decoding base64 sequence",
+ (int) c)));
+#else
+ return 0;
+#endif
+ }
}
/* add it to buffer */
buf = (buf << 6) + b;
@@ -322,23 +162,29 @@ b64_decode(const char *src, unsigned len, char *dst)
}
if (pos != 0)
+ {
+#ifndef FRONTEND
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("invalid base64 end sequence"),
errhint("Input data is missing padding, is truncated, or is otherwise corrupted.")));
+#else
+ return 0;
+#endif
+ }
return p - dst;
}
-static unsigned
+unsigned
b64_enc_len(const char *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
+unsigned
b64_dec_len(const char *src, unsigned srclen)
{
return (srclen * 3) >> 2;
@@ -361,7 +207,7 @@ b64_dec_len(const char *src, unsigned srclen)
#define VAL(CH) ((CH) - '0')
#define DIG(VAL) ((VAL) + '0')
-static unsigned
+unsigned
esc_encode(const char *src, unsigned srclen, char *dst)
{
const char *end = src + srclen;
@@ -400,7 +246,7 @@ esc_encode(const char *src, unsigned srclen, char *dst)
return len;
}
-static unsigned
+unsigned
esc_decode(const char *src, unsigned srclen, char *dst)
{
const char *end = src + srclen;
@@ -437,9 +283,13 @@ esc_decode(const char *src, unsigned srclen, char *dst)
* One backslash, not followed by ### valid octal. Should never
* get here, since esc_dec_len does same check.
*/
+#ifndef FRONTEND
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input syntax for type bytea")));
+#else
+ return 0;
+#endif
}
len++;
@@ -448,7 +298,7 @@ esc_decode(const char *src, unsigned srclen, char *dst)
return len;
}
-static unsigned
+unsigned
esc_enc_len(const char *src, unsigned srclen)
{
const char *end = src + srclen;
@@ -469,7 +319,7 @@ esc_enc_len(const char *src, unsigned srclen)
return len;
}
-static unsigned
+unsigned
esc_dec_len(const char *src, unsigned srclen)
{
const char *end = src + srclen;
@@ -502,9 +352,13 @@ esc_dec_len(const char *src, unsigned srclen)
/*
* one backslash, not followed by ### valid octal
*/
+#ifndef FRONTEND
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input syntax for type bytea")));
+#else
+ return 0;
+#endif
}
len++;
@@ -513,50 +367,104 @@ esc_dec_len(const char *src, unsigned srclen)
}
/*
- * Common
+ * HEX
*/
-static const struct
-{
- const char *name;
- struct pg_encoding enc;
-} enclist[] =
+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,
+};
+unsigned
+hex_encode(const char *src, unsigned len, char *dst)
{
+ const char *end = src + len;
+
+ while (src < end)
{
- "hex",
- {
- hex_enc_len, hex_dec_len, hex_encode, hex_decode
- }
- },
+ *dst++ = hextbl[(*src >> 4) & 0xF];
+ *dst++ = hextbl[*src & 0xF];
+ src++;
+ }
+ return len * 2;
+}
+
+static inline char
+get_hex(char c)
+{
+ int res = -1;
+
+ if (c > 0 && c < 127)
+ res = hexlookup[(unsigned char) c];
+
+ if (res < 0)
{
- "base64",
- {
- b64_enc_len, b64_dec_len, b64_encode, b64_decode
- }
- },
+#ifndef FRONTEND
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid hexadecimal digit: \"%c\"", c)));
+#else
+ return 0;
+#endif
+ }
+
+ return (char) res;
+}
+
+unsigned
+hex_decode(const char *src, unsigned len, char *dst)
+{
+ const char *s,
+ *srcend;
+ char v1,
+ v2,
+ *p;
+
+ srcend = src + len;
+ s = src;
+ p = dst;
+ while (s < srcend)
{
- "escape",
+ if (*s == ' ' || *s == '\n' || *s == '\t' || *s == '\r')
{
- esc_enc_len, esc_dec_len, esc_encode, esc_decode
+ s++;
+ continue;
}
- },
- {
- NULL,
+ v1 = get_hex(*s++) << 4;
+ if (s >= srcend)
{
- NULL, NULL, NULL, NULL
+#ifndef FRONTEND
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid hexadecimal data: odd number of digits")));
+#else
+ return 0;
+#endif
}
+
+ v2 = get_hex(*s++);
+ *p++ = v1 | v2;
}
-};
-static const struct pg_encoding *
-pg_find_encoding(const char *name)
-{
- int i;
+ return p - dst;
+}
- for (i = 0; enclist[i].name; i++)
- if (pg_strcasecmp(enclist[i].name, name) == 0)
- return &enclist[i].enc;
+unsigned
+hex_enc_len(const char *src, unsigned srclen)
+{
+ return srclen << 1;
+}
- return NULL;
+unsigned
+hex_dec_len(const char *src, unsigned srclen)
+{
+ return srclen >> 1;
}
diff --git a/src/include/common/encode.h b/src/include/common/encode.h
new file mode 100644
index 0000000..8166376
--- /dev/null
+++ b/src/include/common/encode.h
@@ -0,0 +1,30 @@
+/*
+ * encode.h
+ * Encoding and decoding routines for base64, hexadecimal and escape.
+ *
+ * Portions Copyright (c) 2001-2016, PostgreSQL Global Development Group
+ *
+ * src/include/common/encode.h
+ */
+#ifndef COMMON_ENCODE_H
+#define COMMON_ENCODE_H
+
+/* base 64 */
+unsigned b64_encode(const char *src, unsigned len, char *dst);
+unsigned b64_decode(const char *src, unsigned len, char *dst);
+unsigned b64_enc_len(const char *src, unsigned srclen);
+unsigned b64_dec_len(const char *src, unsigned srclen);
+
+/* hex */
+unsigned hex_encode(const char *src, unsigned len, char *dst);
+unsigned hex_decode(const char *src, unsigned len, char *dst);
+unsigned hex_enc_len(const char *src, unsigned srclen);
+unsigned hex_dec_len(const char *src, unsigned srclen);
+
+/* escape */
+unsigned esc_encode(const char *src, unsigned srclen, char *dst);
+unsigned esc_decode(const char *src, unsigned srclen, char *dst);
+unsigned esc_enc_len(const char *src, unsigned srclen);
+unsigned esc_dec_len(const char *src, unsigned srclen);
+
+#endif /* COMMON_ENCODE_H */
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index 8cebc86..5791347 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -156,8 +156,6 @@ extern int errdomainconstraint(Oid datatypeOid, const char *conname);
/* encode.c */
extern Datum binary_encode(PG_FUNCTION_ARGS);
extern Datum binary_decode(PG_FUNCTION_ARGS);
-extern unsigned hex_encode(const char *src, unsigned len, char *dst);
-extern unsigned hex_decode(const char *src, unsigned len, char *dst);
/* enum.c */
extern Datum enum_in(PG_FUNCTION_ARGS);
diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm
index 02a3fc7..b6908c2 100644
--- a/src/tools/msvc/Mkvcbuild.pm
+++ b/src/tools/msvc/Mkvcbuild.pm
@@ -110,7 +110,7 @@ sub mkvcbuild
}
our @pgcommonallfiles = qw(
- config_info.c controldata_utils.c exec.c keywords.c
+ config_info.c controldata_utils.c encode.c exec.c keywords.c
pg_lzcompress.c pgfnames.c psprintf.c relpath.c rmtree.c
string.c username.c wait_error.c);
--
2.9.2