mirror of
https://github.com/postgres/postgres.git
synced 2025-06-11 20:28:21 +03:00
Update of contrib stuff from massimo.
This commit is contained in:
@ -14,17 +14,19 @@
|
||||
#include "utils/palloc.h"
|
||||
#include "utils/builtins.h"
|
||||
|
||||
#include "string_io.h"
|
||||
|
||||
/* define this if you want to see iso-8859 characters */
|
||||
#define ISO8859
|
||||
|
||||
#define MIN(x, y) ((x) < (y) ? (x) : (y))
|
||||
#define VALUE(char) ((char) - '0')
|
||||
#define DIGIT(val) ((val) + '0')
|
||||
#define ISOCTAL(c) (((c) >= '0') && ((c) <= '7'))
|
||||
#define MIN(x, y) ((x) < (y) ? (x) : (y))
|
||||
#define VALUE(char) ((char) - '0')
|
||||
#define DIGIT(val) ((val) + '0')
|
||||
#define ISOCTAL(c) (((c) >= '0') && ((c) <= '7'))
|
||||
#ifndef ISO8859
|
||||
#define NOTPRINTABLE(c) (!isprint(c))
|
||||
#define NOTPRINTABLE(c) (!isprint(c))
|
||||
#else
|
||||
#define NOTPRINTABLE(c) (!isprint(c) && ((c) < 0xa0))
|
||||
#define NOTPRINTABLE(c) (!isprint(c) && ((c) < 0xa0))
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -36,129 +38,115 @@
|
||||
* The function is used by output methods of various string types.
|
||||
*
|
||||
* Arguments:
|
||||
* data - input data (can be NULL)
|
||||
* size - optional size of data. A negative value indicates
|
||||
* that data is a null terminated string.
|
||||
* data - input data (can be NULL)
|
||||
* size - optional size of data. A negative value indicates
|
||||
* that data is a null terminated string.
|
||||
*
|
||||
* Returns:
|
||||
* a pointer to a new string containing the printable
|
||||
* representation of data.
|
||||
* a pointer to a new string containing the printable
|
||||
* representation of data.
|
||||
*/
|
||||
|
||||
char *
|
||||
char *
|
||||
string_output(char *data, int size)
|
||||
{
|
||||
register unsigned char c,
|
||||
*p,
|
||||
*r,
|
||||
*result;
|
||||
register int l,
|
||||
len;
|
||||
register unsigned char c, *p, *r, *result;
|
||||
register int l, len;
|
||||
|
||||
if (data == NULL)
|
||||
{
|
||||
result = (char *) palloc(2);
|
||||
result[0] = '-';
|
||||
result[1] = '\0';
|
||||
return (result);
|
||||
if (data == NULL) {
|
||||
result = (char *) palloc(2);
|
||||
result[0] = '-';
|
||||
result[1] = '\0';
|
||||
return (result);
|
||||
}
|
||||
|
||||
if (size < 0) {
|
||||
size = strlen(data);
|
||||
}
|
||||
|
||||
/* adjust string length for escapes */
|
||||
len = size;
|
||||
for (p=data,l=size; l>0; p++,l--) {
|
||||
switch (*p) {
|
||||
case '\\':
|
||||
case '"' :
|
||||
case '{':
|
||||
case '}':
|
||||
case '\b':
|
||||
case '\f':
|
||||
case '\n':
|
||||
case '\r':
|
||||
case '\t':
|
||||
case '\v':
|
||||
len++;
|
||||
break;
|
||||
default:
|
||||
if (NOTPRINTABLE(*p)) {
|
||||
len += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
len++;
|
||||
|
||||
if (size < 0)
|
||||
{
|
||||
size = strlen(data);
|
||||
result = (char *) palloc(len);
|
||||
|
||||
for (p=data,r=result,l=size; (l > 0) && (c = *p); p++,l--) {
|
||||
switch (c) {
|
||||
case '\\':
|
||||
case '"' :
|
||||
case '{':
|
||||
case '}':
|
||||
*r++ = '\\';
|
||||
*r++ = c;
|
||||
break;
|
||||
case '\b':
|
||||
*r++ = '\\';
|
||||
*r++ = 'b';
|
||||
break;
|
||||
case '\f':
|
||||
*r++ = '\\';
|
||||
*r++ = 'f';
|
||||
break;
|
||||
case '\n':
|
||||
*r++ = '\\';
|
||||
*r++ = 'n';
|
||||
break;
|
||||
case '\r':
|
||||
*r++ = '\\';
|
||||
*r++ = 'r';
|
||||
break;
|
||||
case '\t':
|
||||
*r++ = '\\';
|
||||
*r++ = 't';
|
||||
break;
|
||||
case '\v':
|
||||
*r++ = '\\';
|
||||
*r++ = 'v';
|
||||
break;
|
||||
default:
|
||||
if (NOTPRINTABLE(c)) {
|
||||
*r = '\\';
|
||||
r += 3;
|
||||
*r-- = DIGIT(c & 07);
|
||||
c >>= 3;
|
||||
*r-- = DIGIT(c & 07);
|
||||
c >>= 3;
|
||||
*r = DIGIT(c & 03);
|
||||
r += 3;
|
||||
} else {
|
||||
*r++ = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
*r = '\0';
|
||||
|
||||
/* adjust string length for escapes */
|
||||
len = size;
|
||||
for (p = data, l = size; l > 0; p++, l--)
|
||||
{
|
||||
switch (*p)
|
||||
{
|
||||
case '\\':
|
||||
case '"':
|
||||
case '{':
|
||||
case '}':
|
||||
case '\b':
|
||||
case '\f':
|
||||
case '\n':
|
||||
case '\r':
|
||||
case '\t':
|
||||
case '\v':
|
||||
len++;
|
||||
break;
|
||||
default:
|
||||
if (NOTPRINTABLE(*p))
|
||||
{
|
||||
len += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
len++;
|
||||
|
||||
result = (char *) palloc(len);
|
||||
|
||||
for (p = data, r = result, l = size; (l > 0) && (c = *p); p++, l--)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '\\':
|
||||
case '"':
|
||||
case '{':
|
||||
case '}':
|
||||
*r++ = '\\';
|
||||
*r++ = c;
|
||||
break;
|
||||
case '\b':
|
||||
*r++ = '\\';
|
||||
*r++ = 'b';
|
||||
break;
|
||||
case '\f':
|
||||
*r++ = '\\';
|
||||
*r++ = 'f';
|
||||
break;
|
||||
case '\n':
|
||||
*r++ = '\\';
|
||||
*r++ = 'n';
|
||||
break;
|
||||
case '\r':
|
||||
*r++ = '\\';
|
||||
*r++ = 'r';
|
||||
break;
|
||||
case '\t':
|
||||
*r++ = '\\';
|
||||
*r++ = 't';
|
||||
break;
|
||||
case '\v':
|
||||
*r++ = '\\';
|
||||
*r++ = 'v';
|
||||
break;
|
||||
default:
|
||||
if (NOTPRINTABLE(c))
|
||||
{
|
||||
*r = '\\';
|
||||
r += 3;
|
||||
*r-- = DIGIT(c & 07);
|
||||
c >>= 3;
|
||||
*r-- = DIGIT(c & 07);
|
||||
c >>= 3;
|
||||
*r = DIGIT(c & 03);
|
||||
r += 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
*r++ = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
*r = '\0';
|
||||
|
||||
return ((char *) result);
|
||||
return((char *) result);
|
||||
}
|
||||
|
||||
/*
|
||||
* string_input() --
|
||||
*
|
||||
* This function accepts a C string in input and copies it into a new
|
||||
* This function accepts a C string in input and copies it into a new
|
||||
* object allocated with palloc() translating all escape sequences.
|
||||
* An optional header can be allocatd before the string, for example
|
||||
* to hold the length of a varlena object.
|
||||
@ -167,231 +155,211 @@ string_output(char *data, int size)
|
||||
* receive strings in internal form.
|
||||
*
|
||||
* Arguments:
|
||||
* str - input string possibly with escapes
|
||||
* size - the required size of new data. A value of 0
|
||||
* indicates a variable size string, while a
|
||||
* negative value indicates a variable size string
|
||||
* of size not greater than this absolute value.
|
||||
* hdrsize - size of an optional header to be allocated before
|
||||
* the data. It must then be filled by the caller.
|
||||
* rtn_size - an optional pointer to an int variable where the
|
||||
* size of the new string is stored back.
|
||||
* str - input string possibly with escapes
|
||||
* size - the required size of new data. A value of 0
|
||||
* indicates a variable size string, while a
|
||||
* negative value indicates a variable size string
|
||||
* of size not greater than this absolute value.
|
||||
* hdrsize - size of an optional header to be allocated before
|
||||
* the data. It must then be filled by the caller.
|
||||
* rtn_size - an optional pointer to an int variable where the
|
||||
* size of the new string is stored back.
|
||||
*
|
||||
* Returns:
|
||||
* a pointer to the new string or the header.
|
||||
* a pointer to the new string or the header.
|
||||
*/
|
||||
|
||||
char *
|
||||
char *
|
||||
string_input(char *str, int size, int hdrsize, int *rtn_size)
|
||||
{
|
||||
register unsigned char *p,
|
||||
*r;
|
||||
unsigned char *result;
|
||||
int len;
|
||||
register unsigned char *p, *r;
|
||||
unsigned char *result;
|
||||
int len;
|
||||
|
||||
if ((str == NULL) || (hdrsize < 0))
|
||||
{
|
||||
return (char *) NULL;
|
||||
}
|
||||
if ((str == NULL) || (hdrsize < 0)) {
|
||||
return (char *) NULL;
|
||||
}
|
||||
|
||||
/* Compute result size */
|
||||
len = strlen(str);
|
||||
for (p = str; *p;)
|
||||
{
|
||||
if (*p++ == '\\')
|
||||
{
|
||||
if (ISOCTAL(*p))
|
||||
{
|
||||
if (ISOCTAL(*(p + 1)))
|
||||
{
|
||||
p++;
|
||||
len--;
|
||||
}
|
||||
if (ISOCTAL(*(p + 1)))
|
||||
{
|
||||
p++;
|
||||
len--;
|
||||
}
|
||||
}
|
||||
if (*p)
|
||||
p++;
|
||||
len--;
|
||||
/* Compute result size */
|
||||
len = strlen(str);
|
||||
for (p=str; *p; ) {
|
||||
if (*p++ == '\\') {
|
||||
if (ISOCTAL(*p)) {
|
||||
if (ISOCTAL(*(p+1))) {
|
||||
p++;
|
||||
len--;
|
||||
}
|
||||
}
|
||||
|
||||
/* result has variable length */
|
||||
if (size == 0)
|
||||
{
|
||||
size = len + 1;
|
||||
}
|
||||
else
|
||||
/* result has variable length with maximum size */
|
||||
if (size < 0)
|
||||
{
|
||||
size = MIN(len, -size) + 1;
|
||||
}
|
||||
|
||||
result = (char *) palloc(hdrsize + size);
|
||||
memset(result, 0, hdrsize + size);
|
||||
if (rtn_size)
|
||||
{
|
||||
*rtn_size = size;
|
||||
}
|
||||
|
||||
r = result + hdrsize;
|
||||
for (p = str; *p;)
|
||||
{
|
||||
register unsigned char c;
|
||||
|
||||
if ((c = *p++) == '\\')
|
||||
{
|
||||
switch (c = *p++)
|
||||
{
|
||||
case '\0':
|
||||
p--;
|
||||
break;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
c = VALUE(c);
|
||||
if (isdigit(*p))
|
||||
{
|
||||
c = (c << 3) + VALUE(*p++);
|
||||
}
|
||||
if (isdigit(*p))
|
||||
{
|
||||
c = (c << 3) + VALUE(*p++);
|
||||
}
|
||||
*r++ = c;
|
||||
break;
|
||||
case 'b':
|
||||
*r++ = '\b';
|
||||
break;
|
||||
case 'f':
|
||||
*r++ = '\f';
|
||||
break;
|
||||
case 'n':
|
||||
*r++ = '\n';
|
||||
break;
|
||||
case 'r':
|
||||
*r++ = '\r';
|
||||
break;
|
||||
case 't':
|
||||
*r++ = '\t';
|
||||
break;
|
||||
case 'v':
|
||||
*r++ = '\v';
|
||||
break;
|
||||
default:
|
||||
*r++ = c;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*r++ = c;
|
||||
if (ISOCTAL(*(p+1))) {
|
||||
p++;
|
||||
len--;
|
||||
}
|
||||
}
|
||||
if (*p) p++;
|
||||
len--;
|
||||
}
|
||||
}
|
||||
|
||||
return ((char *) result);
|
||||
/* result has variable length */
|
||||
if (size == 0) {
|
||||
size = len+1;
|
||||
} else
|
||||
|
||||
/* result has variable length with maximum size */
|
||||
if (size < 0) {
|
||||
size = MIN(len, - size)+1;
|
||||
}
|
||||
|
||||
result = (char *) palloc(hdrsize+size);
|
||||
memset(result, 0, hdrsize+size);
|
||||
if (rtn_size) {
|
||||
*rtn_size = size;
|
||||
}
|
||||
|
||||
r = result + hdrsize;
|
||||
for (p=str; *p; ) {
|
||||
register unsigned char c;
|
||||
if ((c = *p++) == '\\') {
|
||||
switch (c = *p++) {
|
||||
case '\0':
|
||||
p--;
|
||||
break;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
c = VALUE(c);
|
||||
if (isdigit(*p)) {
|
||||
c = (c<<3) + VALUE(*p++);
|
||||
}
|
||||
if (isdigit(*p)) {
|
||||
c = (c<<3) + VALUE(*p++);
|
||||
}
|
||||
*r++ = c;
|
||||
break;
|
||||
case 'b':
|
||||
*r++ = '\b';
|
||||
break;
|
||||
case 'f':
|
||||
*r++ = '\f';
|
||||
break;
|
||||
case 'n':
|
||||
*r++ = '\n';
|
||||
break;
|
||||
case 'r':
|
||||
*r++ = '\r';
|
||||
break;
|
||||
case 't':
|
||||
*r++ = '\t';
|
||||
break;
|
||||
case 'v':
|
||||
*r++ = '\v';
|
||||
break;
|
||||
default:
|
||||
*r++ = c;
|
||||
}
|
||||
} else {
|
||||
*r++ = c;
|
||||
}
|
||||
}
|
||||
|
||||
return((char *) result);
|
||||
}
|
||||
|
||||
char *
|
||||
char *
|
||||
c_charout(int32 c)
|
||||
{
|
||||
char str[2];
|
||||
char str[2];
|
||||
|
||||
str[0] = (char) c;
|
||||
str[1] = '\0';
|
||||
str[0] = (char) c;
|
||||
str[1] = '\0';
|
||||
|
||||
return (string_output(str, 1));
|
||||
return (string_output(str, 1));
|
||||
}
|
||||
|
||||
char *
|
||||
char *
|
||||
c_char2out(uint16 s)
|
||||
{
|
||||
return (string_output((char *) &s, 2));
|
||||
return (string_output((char *) &s, 2));
|
||||
}
|
||||
|
||||
char *
|
||||
char *
|
||||
c_char4out(uint32 s)
|
||||
{
|
||||
return (string_output((char *) &s, 4));
|
||||
return (string_output((char *) &s, 4));
|
||||
}
|
||||
|
||||
char *
|
||||
char *
|
||||
c_char8out(char *s)
|
||||
{
|
||||
return (string_output(s, 8));
|
||||
return (string_output(s, 8));
|
||||
}
|
||||
|
||||
char *
|
||||
char *
|
||||
c_char16out(char *s)
|
||||
{
|
||||
return (string_output(s, 16));
|
||||
return (string_output(s, 16));
|
||||
}
|
||||
|
||||
/*
|
||||
* This can be used for text, bytea, SET and unknown data types
|
||||
*/
|
||||
|
||||
char *
|
||||
c_textout(struct varlena * vlena)
|
||||
char *
|
||||
c_textout(struct varlena *vlena)
|
||||
{
|
||||
int len = 0;
|
||||
char *s = NULL;
|
||||
int len = 0;
|
||||
char *s = NULL;
|
||||
|
||||
if (vlena)
|
||||
{
|
||||
len = VARSIZE(vlena) - VARHDRSZ;
|
||||
s = VARDATA(vlena);
|
||||
}
|
||||
return (string_output(s, len));
|
||||
if (vlena) {
|
||||
len = VARSIZE(vlena) - VARHDRSZ;
|
||||
s = VARDATA(vlena);
|
||||
}
|
||||
return (string_output(s, len));
|
||||
}
|
||||
|
||||
/*
|
||||
* This can be used for varchar and bpchar strings
|
||||
*/
|
||||
|
||||
char *
|
||||
char *
|
||||
c_varcharout(char *s)
|
||||
{
|
||||
int len;
|
||||
int len = 0;
|
||||
|
||||
if (s)
|
||||
{
|
||||
len = *(int32 *) s - 4;
|
||||
s += 4;
|
||||
}
|
||||
return (string_output(s, len));
|
||||
if (s) {
|
||||
len = *(int32*)s - 4;
|
||||
s += 4;
|
||||
}
|
||||
return (string_output(s, len));
|
||||
}
|
||||
|
||||
#ifdef 0
|
||||
#if 0
|
||||
struct varlena *
|
||||
c_textin(char *str)
|
||||
{
|
||||
struct varlena *result;
|
||||
int len;
|
||||
struct varlena *result;
|
||||
int len;
|
||||
|
||||
if (str == NULL)
|
||||
{
|
||||
return ((struct varlena *) NULL);
|
||||
}
|
||||
if (str == NULL) {
|
||||
return ((struct varlena *) NULL);
|
||||
}
|
||||
|
||||
result = (struct varlena *) string_input(str, 0, VARHDRSZ, &len);
|
||||
VARSIZE(result) = len;
|
||||
result = (struct varlena *) string_input(str, 0, VARHDRSZ, &len);
|
||||
VARSIZE(result) = len;
|
||||
|
||||
return (result);
|
||||
return (result);
|
||||
}
|
||||
|
||||
char *
|
||||
char *
|
||||
c_char16in(char *str)
|
||||
{
|
||||
return (string_input(str, 16, 0, NULL));
|
||||
return (string_input(str, 16, 0, NULL));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* end of file */
|
||||
|
Reference in New Issue
Block a user