aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils')
-rw-r--r--src/backend/utils/adt/lztext.c145
-rw-r--r--src/backend/utils/adt/pg_lzcompress.c166
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++));
+}
+
+