summaryrefslogtreecommitdiff
path: root/src/common/pg_lzcompress.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/pg_lzcompress.c')
-rw-r--r--src/common/pg_lzcompress.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/src/common/pg_lzcompress.c b/src/common/pg_lzcompress.c
index 988b3987d04..3adad62d9a4 100644
--- a/src/common/pg_lzcompress.c
+++ b/src/common/pg_lzcompress.c
@@ -771,3 +771,40 @@ pglz_decompress(const char *source, int32 slen, char *dest,
*/
return (char *) dp - dest;
}
+
+
+/* ----------
+ * pglz_max_compressed_size -
+ *
+ * Calculate the maximum compressed size for a given amount of raw data.
+ * Return the maximum size, or total compressed size if maximum size is
+ * larger than total compressed size.
+ *
+ * We can't use PGLZ_MAX_OUTPUT for this purpose, because that's used to size
+ * the compression buffer (and abort the compression). It does not really say
+ * what's the maximum compressed size for an input of a given length, and it
+ * may happen that while the whole value is compressible (and thus fits into
+ * PGLZ_MAX_OUTPUT nicely), the prefix is not compressible at all.
+ * ----------
+ */
+int32
+pglz_maximum_compressed_size(int32 rawsize, int32 total_compressed_size)
+{
+ int32 compressed_size;
+
+ /*
+ * pglz uses one control bit per byte, so we need (rawsize * 9) bits. We
+ * care about bytes though, so we add 7 to make sure we include the last
+ * incomplete byte (integer division rounds down).
+ *
+ * XXX Use int64 to prevent overflow during calculation.
+ */
+ compressed_size = (int32) ((int64) rawsize * 9 + 7) / 8;
+
+ /*
+ * Maximum compressed size can't be larger than total compressed size.
+ */
+ compressed_size = Min(compressed_size, total_compressed_size);
+
+ return compressed_size;
+}