Index: fe-exec.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v retrieving revision 1.113 diff -c -r1.113 fe-exec.c *** fe-exec.c 2001/10/25 05:50:13 1.113 --- fe-exec.c 2001/12/28 01:45:34 *************** *** 180,185 **** --- 180,274 ---- return result; } + /* + * PQunescapeBytea - converts the null terminated string representation + * of a bytea, strtext, into binary, filling a buffer. It returns a + * pointer to the buffer which is NULL on error, and the size of the + * buffer in retbuflen. The pointer may subsequently be used as an + * argument to the function free(3). It is the reverse of PQescapeBytea. + * + * The following transformations are reversed: + * '\0' == ASCII 0 == \000 + * '\'' == ASCII 39 == \' + * '\\' == ASCII 92 == \\ + * + * States: + * 0 normal 0->1->2->3->4 + * 1 \ 1->5 + * 2 \0 1->6 + * 3 \00 + * 4 \000 + * 5 \' + * 6 \\ + */ + unsigned char * + PQunescapeBytea(unsigned char *strtext, size_t *retbuflen) + { + size_t buflen; + unsigned char *buffer, *sp, *bp; + unsigned int state=0; + + if(strtext == NULL)return NULL; + buflen = strlen(strtext); /* will shrink, also we discover if strtext */ + buffer = (unsigned char *) malloc(buflen); /* isn't NULL terminated */ + if(buffer == NULL)return NULL; + for(bp = buffer, sp = strtext; *sp != '\0'; bp++, sp++) + { + switch(state) + { + case 0: + if(*sp == '\\')state=1; + *bp = *sp; + break; + case 1: + if(*sp == '\'') /* state=5 */ + { /* replace \' with 39 */ + bp--; + *bp = 39; + buflen--; + state=0; + } + else if(*sp == '\\') /* state=6 */ + { /* replace \\ with 92 */ + bp--; + *bp = 92; + buflen--; + state=0; + } + else + { + if(*sp == '0')state=2; + else state=0; + *bp = *sp; + } + break; + case 2: + if(*sp == '0')state=3; + else state=0; + *bp = *sp; + break; + case 3: + if(*sp == '0') /* state=4 */ + { + bp -= 3; + *bp = 0; + buflen -= 3; + state=0; + } + else + { + *bp = *sp; + state=0; + } + break; + } + } + realloc(buffer,buflen); + + *retbuflen=buflen; + return buffer; + } + /* ---------------- * Space management for PGresult. * Index: libpq-fe.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/interfaces/libpq/libpq-fe.h,v retrieving revision 1.80 diff -c -r1.80 libpq-fe.h *** libpq-fe.h 2001/11/08 20:37:52 1.80 --- libpq-fe.h 2001/12/28 01:45:35 *************** *** 252,257 **** --- 252,260 ---- extern size_t PQescapeString(char *to, const char *from, size_t length); extern unsigned char *PQescapeBytea(unsigned char *bintext, size_t binlen, size_t *bytealen); + extern unsigned char *PQunescapeBytea(unsigned char *strtext, + size_t *retbuflen); + /* Simple synchronous query */ extern PGresult *PQexec(PGconn *conn, const char *query); Index: libpq.sgml =================================================================== RCS file: /projects/cvsroot/pgsql/doc/src/sgml/libpq.sgml,v retrieving revision 1.84 diff -c -r1.84 libpq.sgml *** libpq.sgml 2001/11/29 16:01:15 1.84 --- libpq.sgml 2001/12/28 01:47:16 *************** *** 950,955 **** --- 950,974 ---- character is also added. The single quotes that must surround PostgreSQL string literals are not part of the result string. + + + PQunescapeBytea + Converts an escaped string representation of binary data into binary + data - the reverse of PQescapeBytea. + + unsigned char *PQunescapeBytea(unsigned char *from, size_t *to_length); + + + The from parameter points to an escaped string + such as might be returned by PQgetvalue of a + BYTEA column. PQunescapeBytea converts + this NUL terminated string representation into binary, filling a buffer. + It returns a pointer to the buffer which is NULL on error, and the size + of the buffer in to_length. The pointer may + subsequently be used as an argument to the function + free(3). + +