Обсуждение: Lonely Patch Seeks Long-Term Commitment to Codebase
Hi,
I sent a patch to this list earlier this month to improve the speed of
PGunescapeBytea(). IMHO it is handicapped as it can take over a minute
to process a large amount of data, e.g. a 500Kb JPEG.
The attached patch replaces the sscanf function that causes the delay,
the code was borrowed from the PostgreSQL Python interface with
permission from the author.
Please could I have some feedback on whether the patch is likely to be
committed? Has it been rejected? Is it stuck on someone's TODO list? Was
the code unsuitable? Have I neglected some procedure, etc?
Best regards,
Ben Lamb.
--- fe-exec.c Thu May 8 11:49:34 2003
+++ fe-exec.c.latest Thu May 8 11:45:17 2003
@@ -180,6 +180,8 @@
return result;
}
+#define VAL(CH) ((CH) - '0')
+
/*
* PQunescapeBytea - converts the null terminated string representation
* of a bytea, strtext, into binary, filling a buffer. It returns a
@@ -187,101 +189,66 @@
* 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 == \\
+ * The following transformations are made:
+ * \' == ASCII 39 == '
+ * \\ == ASCII 92 == \
+ * \ooo == a byte whose value = ooo (ooo is an octal number)
+ * \x == x (x is any character not matched by the above transformations)
*
- * 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;
+ size_t strtextlen, buflen;
+ unsigned char *buffer, *tmpbuf;
+ int i, j, byte;
- if (strtext == NULL)
+ if (strtext == NULL) {
return NULL;
- buflen = strlen(strtext); /* will shrink, also we discover if
- * strtext */
- buffer = (unsigned char *) malloc(buflen); /* isn't NULL terminated */
+ }
+
+ strtextlen = strlen(strtext); /* will shrink, also we discover if
+ * strtext isn't NULL terminated */
+ buffer = (unsigned char *)malloc(strtextlen);
if (buffer == NULL)
return NULL;
- for (bp = buffer, sp = strtext; *sp != '\0'; bp++, sp++)
+
+ for (i = j = buflen = 0; i < strtextlen;)
{
- switch (state)
+ switch (strtext[i])
{
- case 0:
- if (*sp == '\\')
- state = 1;
- *bp = *sp;
- break;
- case 1:
- if (*sp == '\'') /* state=5 */
- { /* replace \' with 39 */
- bp--;
- *bp = '\'';
- buflen--;
- state = 0;
- }
- else if (*sp == '\\') /* state=6 */
- { /* replace \\ with 92 */
- bp--;
- *bp = '\\';
- buflen--;
- state = 0;
- }
+ case '\\':
+ i++;
+ if (strtext[i] == '\\')
+ buffer[j++] = strtext[i++];
else
{
- if (isdigit(*sp))
- state = 2;
- else
- state = 0;
- *bp = *sp;
+ if ((isdigit(strtext[i])) &&
+ (isdigit(strtext[i+1])) &&
+ (isdigit(strtext[i+2])))
+ {
+ byte = VAL(strtext[i++]);
+ byte = (byte << 3) + VAL(strtext[i++]);
+ buffer[j++] = (byte << 3) + VAL(strtext[i++]);
+ }
}
break;
- case 2:
- if (isdigit(*sp))
- state = 3;
- else
- state = 0;
- *bp = *sp;
- break;
- case 3:
- if (isdigit(*sp)) /* state=4 */
- {
- int v;
- bp -= 3;
- sscanf(sp - 2, "%03o", &v);
- *bp = v;
- buflen -= 3;
- state = 0;
- }
- else
- {
- *bp = *sp;
- state = 0;
- }
- break;
+ default:
+ buffer[j++] = strtext[i++];
}
}
- buffer = realloc(buffer, buflen);
- if (buffer == NULL)
- return NULL;
+ buflen = j; /* buflen is the length of the unquoted data */
+ tmpbuf = realloc(buffer, buflen);
+
+ if (!tmpbuf)
+ {
+ free(buffer);
+ return 0;
+ }
*retbuflen = buflen;
- return buffer;
+ return tmpbuf;
}
/* ----------------
I think Bruce is still working through his backlog of patches. I know I'm
waiting for my pg_autovacuum patch to be applied which was submitted on May
7th.
Just give him some time, he's been working hard on the win32 port, a worthy
and difficult task IMHO.
Matthew
----- Original Message -----
From: "Ben Lamb" <pgsql-patches@zurgy.org>
To: <pgsql-patches@postgresql.org>
Sent: Wednesday, May 28, 2003 3:26 PM
Subject: [PATCHES] Lonely Patch Seeks Long-Term Commitment to Codebase
> Hi,
>
> I sent a patch to this list earlier this month to improve the speed of
> PGunescapeBytea(). IMHO it is handicapped as it can take over a minute
> to process a large amount of data, e.g. a 500Kb JPEG.
>
> The attached patch replaces the sscanf function that causes the delay,
> the code was borrowed from the PostgreSQL Python interface with
> permission from the author.
>
> Please could I have some feedback on whether the patch is likely to be
> committed? Has it been rejected? Is it stuck on someone's TODO list? Was
> the code unsuitable? Have I neglected some procedure, etc?
>
> Best regards,
>
> Ben Lamb.
>
----------------------------------------------------------------------------
----
> --- fe-exec.c Thu May 8 11:49:34 2003
> +++ fe-exec.c.latest Thu May 8 11:45:17 2003
> @@ -180,6 +180,8 @@
> return result;
> }
>
> +#define VAL(CH) ((CH) - '0')
> +
> /*
> * PQunescapeBytea - converts the null terminated string representation
> * of a bytea, strtext, into binary, filling a buffer. It returns a
> @@ -187,101 +189,66 @@
> * 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 == \\
> + * The following transformations are made:
> + * \' == ASCII 39 == '
> + * \\ == ASCII 92 == \
> + * \ooo == a byte whose value = ooo (ooo is an octal number)
> + * \x == x (x is any character not matched by the above
transformations)
> *
> - * 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;
> + size_t strtextlen, buflen;
> + unsigned char *buffer, *tmpbuf;
> + int i, j, byte;
>
> - if (strtext == NULL)
> + if (strtext == NULL) {
> return NULL;
> - buflen = strlen(strtext); /* will shrink, also we discover if
> - * strtext */
> - buffer = (unsigned char *) malloc(buflen); /* isn't NULL terminated */
> + }
> +
> + strtextlen = strlen(strtext); /* will shrink, also we discover if
> + * strtext isn't NULL terminated */
> + buffer = (unsigned char *)malloc(strtextlen);
> if (buffer == NULL)
> return NULL;
> - for (bp = buffer, sp = strtext; *sp != '\0'; bp++, sp++)
> +
> + for (i = j = buflen = 0; i < strtextlen;)
> {
> - switch (state)
> + switch (strtext[i])
> {
> - case 0:
> - if (*sp == '\\')
> - state = 1;
> - *bp = *sp;
> - break;
> - case 1:
> - if (*sp == '\'') /* state=5 */
> - { /* replace \' with 39 */
> - bp--;
> - *bp = '\'';
> - buflen--;
> - state = 0;
> - }
> - else if (*sp == '\\') /* state=6 */
> - { /* replace \\ with 92 */
> - bp--;
> - *bp = '\\';
> - buflen--;
> - state = 0;
> - }
> + case '\\':
> + i++;
> + if (strtext[i] == '\\')
> + buffer[j++] = strtext[i++];
> else
> {
> - if (isdigit(*sp))
> - state = 2;
> - else
> - state = 0;
> - *bp = *sp;
> + if ((isdigit(strtext[i])) &&
> + (isdigit(strtext[i+1])) &&
> + (isdigit(strtext[i+2])))
> + {
> + byte = VAL(strtext[i++]);
> + byte = (byte << 3) + VAL(strtext[i++]);
> + buffer[j++] = (byte << 3) + VAL(strtext[i++]);
> + }
> }
> break;
> - case 2:
> - if (isdigit(*sp))
> - state = 3;
> - else
> - state = 0;
> - *bp = *sp;
> - break;
> - case 3:
> - if (isdigit(*sp)) /* state=4 */
> - {
> - int v;
>
> - bp -= 3;
> - sscanf(sp - 2, "%03o", &v);
> - *bp = v;
> - buflen -= 3;
> - state = 0;
> - }
> - else
> - {
> - *bp = *sp;
> - state = 0;
> - }
> - break;
> + default:
> + buffer[j++] = strtext[i++];
> }
> }
> - buffer = realloc(buffer, buflen);
> - if (buffer == NULL)
> - return NULL;
> + buflen = j; /* buflen is the length of the unquoted data */
> + tmpbuf = realloc(buffer, buflen);
> +
> + if (!tmpbuf)
> + {
> + free(buffer);
> + return 0;
> + }
>
> *retbuflen = buflen;
> - return buffer;
> + return tmpbuf;
> }
>
> /* ----------------
>
>
----------------------------------------------------------------------------
----
>
> ---------------------------(end of broadcast)---------------------------
> TIP 2: you can get off all lists at once with the unregister command
> (send "unregister YourEmailAddressHere" to majordomo@postgresql.org)
>
I think he said he was going to take a break of about a week to catch up on
patches, so I was waiting till that time was over before making a similar
query. I haven't seen a lot of "Thankyou, this patch has been applied"
messages, though.
cheers
andrew
----- Original Message -----
From: "Matthew T. O'Connor" <matthew@zeut.net>
To: "Ben Lamb" <pgsql-patches@zurgy.org>; <pgsql-patches@postgresql.org>
Sent: Wednesday, May 28, 2003 4:30 PM
Subject: Re: [PATCHES] Lonely Patch Seeks Long-Term Commitment to Codebase
> I think Bruce is still working through his backlog of patches. I know I'm
> waiting for my pg_autovacuum patch to be applied which was submitted on
May
> 7th.
>
> Just give him some time, he's been working hard on the win32 port, a
worthy
> and difficult task IMHO.
>
> Matthew
>
> ----- Original Message -----
> From: "Ben Lamb" <pgsql-patches@zurgy.org>
> To: <pgsql-patches@postgresql.org>
> Sent: Wednesday, May 28, 2003 3:26 PM
> Subject: [PATCHES] Lonely Patch Seeks Long-Term Commitment to Codebase
>
>
> > Hi,
> >
> > I sent a patch to this list earlier this month to improve the speed of
> > PGunescapeBytea(). IMHO it is handicapped as it can take over a minute
> > to process a large amount of data, e.g. a 500Kb JPEG.
> >
> > The attached patch replaces the sscanf function that causes the delay,
> > the code was borrowed from the PostgreSQL Python interface with
> > permission from the author.
> >
> > Please could I have some feedback on whether the patch is likely to be
> > committed? Has it been rejected? Is it stuck on someone's TODO list? Was
> > the code unsuitable? Have I neglected some procedure, etc?
> >
> > Best regards,
> >
> > Ben Lamb.
> >
>
>
> --------------------------------------------------------------------------
--
> ----
>
>
> > --- fe-exec.c Thu May 8 11:49:34 2003
> > +++ fe-exec.c.latest Thu May 8 11:45:17 2003
> > @@ -180,6 +180,8 @@
> > return result;
> > }
> >
> > +#define VAL(CH) ((CH) - '0')
> > +
> > /*
> > * PQunescapeBytea - converts the null terminated string representation
> > * of a bytea, strtext, into binary, filling a buffer. It returns a
> > @@ -187,101 +189,66 @@
> > * 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 == \\
> > + * The following transformations are made:
> > + * \' == ASCII 39 == '
> > + * \\ == ASCII 92 == \
> > + * \ooo == a byte whose value = ooo (ooo is an octal number)
> > + * \x == x (x is any character not matched by the above
> transformations)
> > *
> > - * 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;
> > + size_t strtextlen, buflen;
> > + unsigned char *buffer, *tmpbuf;
> > + int i, j, byte;
> >
> > - if (strtext == NULL)
> > + if (strtext == NULL) {
> > return NULL;
> > - buflen = strlen(strtext); /* will shrink, also we discover if
> > - * strtext */
> > - buffer = (unsigned char *) malloc(buflen); /* isn't NULL terminated */
> > + }
> > +
> > + strtextlen = strlen(strtext); /* will shrink, also we discover if
> > + * strtext isn't NULL terminated */
> > + buffer = (unsigned char *)malloc(strtextlen);
> > if (buffer == NULL)
> > return NULL;
> > - for (bp = buffer, sp = strtext; *sp != '\0'; bp++, sp++)
> > +
> > + for (i = j = buflen = 0; i < strtextlen;)
> > {
> > - switch (state)
> > + switch (strtext[i])
> > {
> > - case 0:
> > - if (*sp == '\\')
> > - state = 1;
> > - *bp = *sp;
> > - break;
> > - case 1:
> > - if (*sp == '\'') /* state=5 */
> > - { /* replace \' with 39 */
> > - bp--;
> > - *bp = '\'';
> > - buflen--;
> > - state = 0;
> > - }
> > - else if (*sp == '\\') /* state=6 */
> > - { /* replace \\ with 92 */
> > - bp--;
> > - *bp = '\\';
> > - buflen--;
> > - state = 0;
> > - }
> > + case '\\':
> > + i++;
> > + if (strtext[i] == '\\')
> > + buffer[j++] = strtext[i++];
> > else
> > {
> > - if (isdigit(*sp))
> > - state = 2;
> > - else
> > - state = 0;
> > - *bp = *sp;
> > + if ((isdigit(strtext[i])) &&
> > + (isdigit(strtext[i+1])) &&
> > + (isdigit(strtext[i+2])))
> > + {
> > + byte = VAL(strtext[i++]);
> > + byte = (byte << 3) + VAL(strtext[i++]);
> > + buffer[j++] = (byte << 3) + VAL(strtext[i++]);
> > + }
> > }
> > break;
> > - case 2:
> > - if (isdigit(*sp))
> > - state = 3;
> > - else
> > - state = 0;
> > - *bp = *sp;
> > - break;
> > - case 3:
> > - if (isdigit(*sp)) /* state=4 */
> > - {
> > - int v;
> >
> > - bp -= 3;
> > - sscanf(sp - 2, "%03o", &v);
> > - *bp = v;
> > - buflen -= 3;
> > - state = 0;
> > - }
> > - else
> > - {
> > - *bp = *sp;
> > - state = 0;
> > - }
> > - break;
> > + default:
> > + buffer[j++] = strtext[i++];
> > }
> > }
> > - buffer = realloc(buffer, buflen);
> > - if (buffer == NULL)
> > - return NULL;
> > + buflen = j; /* buflen is the length of the unquoted data */
> > + tmpbuf = realloc(buffer, buflen);
> > +
> > + if (!tmpbuf)
> > + {
> > + free(buffer);
> > + return 0;
> > + }
> >
> > *retbuflen = buflen;
> > - return buffer;
> > + return tmpbuf;
> > }
> >
> > /* ----------------
> >
> >
>
>
> --------------------------------------------------------------------------
--
> ----
>
>
> >
> > ---------------------------(end of broadcast)---------------------------
> > TIP 2: you can get off all lists at once with the unregister command
> > (send "unregister YourEmailAddressHere" to majordomo@postgresql.org)
> >
>
>
> ---------------------------(end of broadcast)---------------------------
> TIP 2: you can get off all lists at once with the unregister command
> (send "unregister YourEmailAddressHere" to majordomo@postgresql.org)
On Wed, May 28, 2003 at 04:30:39PM -0400, Matthew T. O'Connor wrote: > I think Bruce is still working through his backlog of patches. I know I'm > waiting for my pg_autovacuum patch to be applied which was submitted on May > 7th. Apologies, I'm a newbie and wasn't sure what to expect when I sent the patch to the list. Thanks, Ben.
From: "Ben Lamb" <pgsql-patches@zurgy.org> > Apologies, I'm a newbie and wasn't sure what to expect when I sent the patch to the list. No problem, keep sending patches :-)
Matthew T. O'Connor wrote: > From: "Ben Lamb" <pgsql-patches@zurgy.org> > > Apologies, I'm a newbie and wasn't sure what to expect when I sent the > patch to the list. > > No problem, keep sending patches :-) I am working through my email. I am in early April now, so I have a few weeks to go. These are the emails/patches that need special attention. -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup. | Newtown Square, Pennsylvania 19073
Ben, never mind. I see this is now identical to the newest version of
the patch you posted. Sorry.
---------------------------------------------------------------------------
Ben Lamb wrote:
> Hi,
>
> I sent a patch to this list earlier this month to improve the speed of
> PGunescapeBytea(). IMHO it is handicapped as it can take over a minute
> to process a large amount of data, e.g. a 500Kb JPEG.
>
> The attached patch replaces the sscanf function that causes the delay,
> the code was borrowed from the PostgreSQL Python interface with
> permission from the author.
>
> Please could I have some feedback on whether the patch is likely to be
> committed? Has it been rejected? Is it stuck on someone's TODO list? Was
> the code unsuitable? Have I neglected some procedure, etc?
>
> Best regards,
>
> Ben Lamb.
> --- fe-exec.c Thu May 8 11:49:34 2003
> +++ fe-exec.c.latest Thu May 8 11:45:17 2003
> @@ -180,6 +180,8 @@
> return result;
> }
>
> +#define VAL(CH) ((CH) - '0')
> +
> /*
> * PQunescapeBytea - converts the null terminated string representation
> * of a bytea, strtext, into binary, filling a buffer. It returns a
> @@ -187,101 +189,66 @@
> * 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 == \\
> + * The following transformations are made:
> + * \' == ASCII 39 == '
> + * \\ == ASCII 92 == \
> + * \ooo == a byte whose value = ooo (ooo is an octal number)
> + * \x == x (x is any character not matched by the above transformations)
> *
> - * 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;
> + size_t strtextlen, buflen;
> + unsigned char *buffer, *tmpbuf;
> + int i, j, byte;
>
> - if (strtext == NULL)
> + if (strtext == NULL) {
> return NULL;
> - buflen = strlen(strtext); /* will shrink, also we discover if
> - * strtext */
> - buffer = (unsigned char *) malloc(buflen); /* isn't NULL terminated */
> + }
> +
> + strtextlen = strlen(strtext); /* will shrink, also we discover if
> + * strtext isn't NULL terminated */
> + buffer = (unsigned char *)malloc(strtextlen);
> if (buffer == NULL)
> return NULL;
> - for (bp = buffer, sp = strtext; *sp != '\0'; bp++, sp++)
> +
> + for (i = j = buflen = 0; i < strtextlen;)
> {
> - switch (state)
> + switch (strtext[i])
> {
> - case 0:
> - if (*sp == '\\')
> - state = 1;
> - *bp = *sp;
> - break;
> - case 1:
> - if (*sp == '\'') /* state=5 */
> - { /* replace \' with 39 */
> - bp--;
> - *bp = '\'';
> - buflen--;
> - state = 0;
> - }
> - else if (*sp == '\\') /* state=6 */
> - { /* replace \\ with 92 */
> - bp--;
> - *bp = '\\';
> - buflen--;
> - state = 0;
> - }
> + case '\\':
> + i++;
> + if (strtext[i] == '\\')
> + buffer[j++] = strtext[i++];
> else
> {
> - if (isdigit(*sp))
> - state = 2;
> - else
> - state = 0;
> - *bp = *sp;
> + if ((isdigit(strtext[i])) &&
> + (isdigit(strtext[i+1])) &&
> + (isdigit(strtext[i+2])))
> + {
> + byte = VAL(strtext[i++]);
> + byte = (byte << 3) + VAL(strtext[i++]);
> + buffer[j++] = (byte << 3) + VAL(strtext[i++]);
> + }
> }
> break;
> - case 2:
> - if (isdigit(*sp))
> - state = 3;
> - else
> - state = 0;
> - *bp = *sp;
> - break;
> - case 3:
> - if (isdigit(*sp)) /* state=4 */
> - {
> - int v;
>
> - bp -= 3;
> - sscanf(sp - 2, "%03o", &v);
> - *bp = v;
> - buflen -= 3;
> - state = 0;
> - }
> - else
> - {
> - *bp = *sp;
> - state = 0;
> - }
> - break;
> + default:
> + buffer[j++] = strtext[i++];
> }
> }
> - buffer = realloc(buffer, buflen);
> - if (buffer == NULL)
> - return NULL;
> + buflen = j; /* buflen is the length of the unquoted data */
> + tmpbuf = realloc(buffer, buflen);
> +
> + if (!tmpbuf)
> + {
> + free(buffer);
> + return 0;
> + }
>
> *retbuflen = buflen;
> - return buffer;
> + return tmpbuf;
> }
>
> /* ----------------
>
>
> ---------------------------(end of broadcast)---------------------------
> TIP 2: you can get off all lists at once with the unregister command
> (send "unregister YourEmailAddressHere" to majordomo@postgresql.org)
--
Bruce Momjian | http://candle.pha.pa.us
pgman@candle.pha.pa.us | (610) 359-1001
+ If your life is a hard drive, | 13 Roberts Road
+ Christ can be your backup. | Newtown Square, Pennsylvania 19073
Ben, this patch is slightly different from your previous patch. Is this
the better version?
---------------------------------------------------------------------------
Ben Lamb wrote:
> Hi,
>
> I sent a patch to this list earlier this month to improve the speed of
> PGunescapeBytea(). IMHO it is handicapped as it can take over a minute
> to process a large amount of data, e.g. a 500Kb JPEG.
>
> The attached patch replaces the sscanf function that causes the delay,
> the code was borrowed from the PostgreSQL Python interface with
> permission from the author.
>
> Please could I have some feedback on whether the patch is likely to be
> committed? Has it been rejected? Is it stuck on someone's TODO list? Was
> the code unsuitable? Have I neglected some procedure, etc?
>
> Best regards,
>
> Ben Lamb.
> --- fe-exec.c Thu May 8 11:49:34 2003
> +++ fe-exec.c.latest Thu May 8 11:45:17 2003
> @@ -180,6 +180,8 @@
> return result;
> }
>
> +#define VAL(CH) ((CH) - '0')
> +
> /*
> * PQunescapeBytea - converts the null terminated string representation
> * of a bytea, strtext, into binary, filling a buffer. It returns a
> @@ -187,101 +189,66 @@
> * 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 == \\
> + * The following transformations are made:
> + * \' == ASCII 39 == '
> + * \\ == ASCII 92 == \
> + * \ooo == a byte whose value = ooo (ooo is an octal number)
> + * \x == x (x is any character not matched by the above transformations)
> *
> - * 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;
> + size_t strtextlen, buflen;
> + unsigned char *buffer, *tmpbuf;
> + int i, j, byte;
>
> - if (strtext == NULL)
> + if (strtext == NULL) {
> return NULL;
> - buflen = strlen(strtext); /* will shrink, also we discover if
> - * strtext */
> - buffer = (unsigned char *) malloc(buflen); /* isn't NULL terminated */
> + }
> +
> + strtextlen = strlen(strtext); /* will shrink, also we discover if
> + * strtext isn't NULL terminated */
> + buffer = (unsigned char *)malloc(strtextlen);
> if (buffer == NULL)
> return NULL;
> - for (bp = buffer, sp = strtext; *sp != '\0'; bp++, sp++)
> +
> + for (i = j = buflen = 0; i < strtextlen;)
> {
> - switch (state)
> + switch (strtext[i])
> {
> - case 0:
> - if (*sp == '\\')
> - state = 1;
> - *bp = *sp;
> - break;
> - case 1:
> - if (*sp == '\'') /* state=5 */
> - { /* replace \' with 39 */
> - bp--;
> - *bp = '\'';
> - buflen--;
> - state = 0;
> - }
> - else if (*sp == '\\') /* state=6 */
> - { /* replace \\ with 92 */
> - bp--;
> - *bp = '\\';
> - buflen--;
> - state = 0;
> - }
> + case '\\':
> + i++;
> + if (strtext[i] == '\\')
> + buffer[j++] = strtext[i++];
> else
> {
> - if (isdigit(*sp))
> - state = 2;
> - else
> - state = 0;
> - *bp = *sp;
> + if ((isdigit(strtext[i])) &&
> + (isdigit(strtext[i+1])) &&
> + (isdigit(strtext[i+2])))
> + {
> + byte = VAL(strtext[i++]);
> + byte = (byte << 3) + VAL(strtext[i++]);
> + buffer[j++] = (byte << 3) + VAL(strtext[i++]);
> + }
> }
> break;
> - case 2:
> - if (isdigit(*sp))
> - state = 3;
> - else
> - state = 0;
> - *bp = *sp;
> - break;
> - case 3:
> - if (isdigit(*sp)) /* state=4 */
> - {
> - int v;
>
> - bp -= 3;
> - sscanf(sp - 2, "%03o", &v);
> - *bp = v;
> - buflen -= 3;
> - state = 0;
> - }
> - else
> - {
> - *bp = *sp;
> - state = 0;
> - }
> - break;
> + default:
> + buffer[j++] = strtext[i++];
> }
> }
> - buffer = realloc(buffer, buflen);
> - if (buffer == NULL)
> - return NULL;
> + buflen = j; /* buflen is the length of the unquoted data */
> + tmpbuf = realloc(buffer, buflen);
> +
> + if (!tmpbuf)
> + {
> + free(buffer);
> + return 0;
> + }
>
> *retbuflen = buflen;
> - return buffer;
> + return tmpbuf;
> }
>
> /* ----------------
>
>
> ---------------------------(end of broadcast)---------------------------
> TIP 2: you can get off all lists at once with the unregister command
> (send "unregister YourEmailAddressHere" to majordomo@postgresql.org)
--
Bruce Momjian | http://candle.pha.pa.us
pgman@candle.pha.pa.us | (610) 359-1001
+ If your life is a hard drive, | 13 Roberts Road
+ Christ can be your backup. | Newtown Square, Pennsylvania 19073