diff options
author | Marc G. Fournier <scrappy@hub.org> | 1996-08-18 22:14:33 +0000 |
---|---|---|
committer | Marc G. Fournier <scrappy@hub.org> | 1996-08-18 22:14:33 +0000 |
commit | 9848d3655d44aa2e58d28fe9f93a94b2934eedc8 (patch) | |
tree | 059111c2156111b083ea668b84bc8b3481676fca /contrib/string/string_io.c | |
parent | 1960a3b96573ad1ec73cd50255edde29cc80df88 (diff) | |
download | postgresql-9848d3655d44aa2e58d28fe9f93a94b2934eedc8.tar.gz postgresql-9848d3655d44aa2e58d28fe9f93a94b2934eedc8.zip |
Support Docs & Contrib
Diffstat (limited to 'contrib/string/string_io.c')
-rw-r--r-- | contrib/string/string_io.c | 361 |
1 files changed, 361 insertions, 0 deletions
diff --git a/contrib/string/string_io.c b/contrib/string/string_io.c new file mode 100644 index 00000000000..ab49c5321a3 --- /dev/null +++ b/contrib/string/string_io.c @@ -0,0 +1,361 @@ +/* + * string_io.c -- + * + * This file defines new input/output conversion routines for strings. + * + * Copyright (c) 1996, Massimo Dal Zotto <dz@cs.unitn.it> + */ + +#include <ctype.h> +#include <string.h> + +#include "postgres.h" +#include "utils/elog.h" +#include "utils/palloc.h" +#include "utils/builtins.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')) +#ifndef ISO8859 +#define NOTPRINTABLE(c) (!isprint(c)) +#else +#define NOTPRINTABLE(c) (!isprint(c) && ((c) < 0xa0)) +#endif + +/* + * string_output() -- + * + * This function takes a pointer to a string data and an optional + * data size and returns a printable representation of the data + * translating all escape sequences to C-like \nnn or \c escapes. + * 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. + * + * Returns: + * a pointer to a new string containing the printable + * representation of data. + */ + +char * +string_output(char *data, int size) +{ + 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 (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(c)) { + 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); +} + +/* + * string_input() -- + * + * 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. + * This function is not necessary for input from sql commands because + * the parser already does escape translation, all data input routines + * 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. + * + * Returns: + * a pointer to the new string or the header. + */ + +char * +string_input(char *str, int size, int hdrsize, int *rtn_size) +{ + register unsigned char *p, *r; + unsigned char *result; + int len; + + 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--; + } + } + + /* 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 * +c_charout(int32 c) +{ + char str[2]; + + str[0] = (char) c; + str[1] = '\0'; + + return (string_output(str, 1)); +} + +char * +c_char2out(uint16 s) +{ + return (string_output((char *) &s, 2)); +} + +char * +c_char4out(uint32 s) +{ + return (string_output((char *) &s, 4)); +} + +char * +c_char8out(char *s) +{ + return (string_output(s, 8)); +} + +char * +c_char16out(char *s) +{ + return (string_output(s, 16)); +} + +/* + * This can be used for text, bytea, SET and unknown data types + */ + +char * +c_textout(struct varlena *vlena) +{ + int len = 0; + char *s = NULL; + + if (vlena) { + len = VARSIZE(vlena) - VARHDRSZ; + s = VARDATA(vlena); + } + return (string_output(s, len)); +} + +/* + * This can be used for varchar and bpchar strings + */ + +char * +c_varcharout(char *s) +{ + int len; + + if (s) { + len = *(int32*)s - 4; + s += 4; + } + return (string_output(s, len)); +} + +#ifdef 0 +struct varlena * +c_textin(char *str) +{ + struct varlena *result; + int len; + + if (str == NULL) { + return ((struct varlena *) NULL); + } + + result = (struct varlena *) string_input(str, 0, VARHDRSZ, &len); + VARSIZE(result) = len; + + return (result); +} + +char * +c_char16in(char *str) +{ + return (string_input(str, 16, 0, NULL)); +} +#endif + |