diff options
Diffstat (limited to 'src/backend/utils')
-rw-r--r-- | src/backend/utils/adt/lztext.c | 145 | ||||
-rw-r--r-- | src/backend/utils/adt/pg_lzcompress.c | 166 |
2 files changed, 309 insertions, 2 deletions
diff --git a/src/backend/utils/adt/lztext.c b/src/backend/utils/adt/lztext.c index 6ff128515b6..ef31094fb51 100644 --- a/src/backend/utils/adt/lztext.c +++ b/src/backend/utils/adt/lztext.c @@ -1,7 +1,7 @@ /* ---------- * lztext.c - * - * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/lztext.c,v 1.3 1999/11/24 03:45:12 ishii Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/lztext.c,v 1.4 1999/11/25 01:28:04 wieck Exp $ * * Text type with internal LZ compressed representation. Uses the * standard PostgreSQL compression method. @@ -290,3 +290,146 @@ lztext_text(lztext *lz) } +/* ---------- + * lztext_cmp - + * + * Comparision function for two lztext datum's. + * + * Returns -1, 0 or 1. + * ---------- + */ +int32 +lztext_cmp(lztext *lz1, lztext *lz2) +{ +#ifdef USE_LOCALE + + char *cp1; + char *cp2; + int result; + + if (lz1 == NULL || lz2 == NULL) + return (int32)0; + + cp1 = lztextout(lz1); + cp2 = lztextout(lz2); + + result = strcoll(cp1, cp2); + + pfree(cp1); + pfree(cp2); + + return result; + +#else /* !USE_LOCALE */ + + PGLZ_DecompState ds1; + PGLZ_DecompState ds2; + int c1; + int c2; + int32 result = (int32)0; + + if (lz1 == NULL || lz2 == NULL) + return (int32)0; + + pglz_decomp_init(&ds1, lz1); + pglz_decomp_init(&ds2, lz2); + + for(;;) + { + c1 = pglz_decomp_getchar(&ds1); + c2 = pglz_decomp_getchar(&ds2); + + if (c1 == EOF) + { + if (c2 != EOF) + result = (int32)-1; + break; + } else { + if (c2 == EOF) + { + result = (int32)1; + } + } + if (c1 != c2) + { + result = (int32)(c1 - c2); + break; + } + } + + pglz_decomp_end(&ds1); + pglz_decomp_end(&ds2); + + return result; + +#endif /* USE_LOCALE */ +} + + +/* ---------- + * lztext_eq ... - + * + * =, !=, >, >=, < and <= operator functions for two + * lztext datums. + * ---------- + */ +bool +lztext_eq(lztext *lz1, lztext *lz2) +{ + if (lz1 == NULL || lz2 == NULL) + return false; + + return (bool)(lztext_cmp(lz1, lz2) == 0); +} + + +bool +lztext_ne(lztext *lz1, lztext *lz2) +{ + if (lz1 == NULL || lz2 == NULL) + return false; + + return (bool)(lztext_cmp(lz1, lz2) != 0); +} + + +bool +lztext_gt(lztext *lz1, lztext *lz2) +{ + if (lz1 == NULL || lz2 == NULL) + return false; + + return (bool)(lztext_cmp(lz1, lz2) > 0); +} + + +bool +lztext_ge(lztext *lz1, lztext *lz2) +{ + if (lz1 == NULL || lz2 == NULL) + return false; + + return (bool)(lztext_cmp(lz1, lz2) >= 0); +} + + +bool +lztext_lt(lztext *lz1, lztext *lz2) +{ + if (lz1 == NULL || lz2 == NULL) + return false; + + return (bool)(lztext_cmp(lz1, lz2) < 0); +} + + +bool +lztext_le(lztext *lz1, lztext *lz2) +{ + if (lz1 == NULL || lz2 == NULL) + return false; + + return (bool)(lztext_cmp(lz1, lz2) <= 0); +} + + diff --git a/src/backend/utils/adt/pg_lzcompress.c b/src/backend/utils/adt/pg_lzcompress.c index b3eb5e2a013..c35568e9598 100644 --- a/src/backend/utils/adt/pg_lzcompress.c +++ b/src/backend/utils/adt/pg_lzcompress.c @@ -1,7 +1,7 @@ /* ---------- * pg_lzcompress.c - * - * $Header: /cvsroot/pgsql/src/backend/utils/adt/pg_lzcompress.c,v 1.2 1999/11/17 22:18:45 wieck Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/pg_lzcompress.c,v 1.3 1999/11/25 01:28:04 wieck Exp $ * * This is an implementation of LZ compression for PostgreSQL. * It uses a simple history table and generates 2-3 byte tags @@ -671,3 +671,167 @@ pglz_decompress (PGLZ_Header *source, char *dest) } +/* ---------- + * pglz_get_next_decomp_char_from_lzdata - + * + * Reads the next character from a decompression state if the + * input data to pglz_decomp_init() was in compressed format. + * ---------- + */ +int +pglz_get_next_decomp_char_from_lzdata(PGLZ_DecompState *dstate) +{ + unsigned char retval; + + if (dstate->tocopy > 0) + { + /* ---------- + * Copy one byte from output to output until we did it + * for the length specified by the last tag. Return that + * byte. + * ---------- + */ + dstate->tocopy--; + return (*(dstate->cp_out++) = *(dstate->cp_copy++)); + } + + if (dstate->ctrl_count == 0) + { + /* ---------- + * Get the next control byte if we need to, but check + * for EOF before. + * ---------- + */ + if (dstate->cp_in == dstate->cp_end) + { + return EOF; + } + + /* ---------- + * This decompression method saves time only, if we stop near + * the beginning of the data (maybe because we're called by a + * comparision function and a difference occurs early). Otherwise, + * all the checks, needed here, cause too much overhead. + * + * Thus we decompress the entire rest at once into the temporary + * buffer and change the decomp state to return the prepared + * data from the buffer by the more simple calls to + * pglz_get_next_decomp_char_from_plain(). + * ---------- + */ + if (dstate->cp_out - dstate->temp_buf >= 256) + { + unsigned char *cp_in = dstate->cp_in; + unsigned char *cp_out = dstate->cp_out; + unsigned char *cp_end = dstate->cp_end; + unsigned char *cp_copy; + unsigned char ctrl; + int off; + int len; + int i; + + while (cp_in < cp_end) + { + ctrl = *cp_in++; + + for (i = 0; i < 8; i++) + { + if (cp_in == cp_end) + break; + + if (ctrl & 0x01) + { + len = (cp_in[0] & 0x0f) + 3; + off = ((cp_in[0] & 0xf0) << 4) | cp_in[1]; + cp_in += 2; + if (len == 18) + len += *cp_in++; + + cp_copy = cp_out - off; + while(len--) + *cp_out++ = *cp_copy++; + } else { + *cp_out++ = *cp_in++; + } + ctrl >>= 1; + } + } + + dstate->cp_in = dstate->cp_out; + dstate->cp_end = cp_out; + dstate->next_char = pglz_get_next_decomp_char_from_plain; + + return (int)(*(dstate->cp_in++)); + } + + /* ---------- + * Not yet, get next control byte into decomp state. + * ---------- + */ + dstate->ctrl = (unsigned char)(*(dstate->cp_in++)); + dstate->ctrl_count = 8; + } + + /* ---------- + * Check for EOF in tag/literal byte data. + * ---------- + */ + if (dstate->cp_in == dstate->cp_end) + { + return EOF; + } + + /* ---------- + * Handle next control bit. + * ---------- + */ + dstate->ctrl_count--; + if (dstate->ctrl & 0x01) + { + /* ---------- + * Bit is set, so tag is following. Setup copy information + * and do the copy for the first byte as above. + * ---------- + */ + int off; + + dstate->tocopy = (dstate->cp_in[0] & 0x0f) + 3; + off = ((dstate->cp_in[0] & 0xf0) << 4) | dstate->cp_in[1]; + dstate->cp_in += 2; + if (dstate->tocopy == 18) + dstate->tocopy += *(dstate->cp_in++); + dstate->cp_copy = dstate->cp_out - off; + + dstate->tocopy--; + retval = (*(dstate->cp_out++) = *(dstate->cp_copy++)); + } else { + /* ---------- + * Bit is unset, so literal byte follows. + * ---------- + */ + retval = (int)(*(dstate->cp_out++) = *(dstate->cp_in++)); + } + dstate->ctrl >>= 1; + + return (int)retval; +} + + +/* ---------- + * pglz_get_next_decomp_char_from_plain - + * + * The input data to pglz_decomp_init() was stored in uncompressed + * format. So we don't have a temporary output buffer and simply + * return bytes from the input until EOF. + * ---------- + */ +int +pglz_get_next_decomp_char_from_plain(PGLZ_DecompState *dstate) +{ + if (dstate->cp_in >= dstate->cp_end) + return EOF; + + return (int)(*(dstate->cp_in++)); +} + + |