aboutsummaryrefslogtreecommitdiff
path: root/src/liblzma/common/memory_usage.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/liblzma/common/memory_usage.c')
-rw-r--r--src/liblzma/common/memory_usage.c113
1 files changed, 113 insertions, 0 deletions
diff --git a/src/liblzma/common/memory_usage.c b/src/liblzma/common/memory_usage.c
new file mode 100644
index 00000000..b6f27957
--- /dev/null
+++ b/src/liblzma/common/memory_usage.c
@@ -0,0 +1,113 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file memory_usage.c
+/// \brief Calculate rough amount of memory required by filters
+//
+// Copyright (C) 2007 Lasse Collin
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "common.h"
+#include "lz_encoder.h"
+#include "lzma_literal.h"
+
+
+static uint64_t
+get_usage(const lzma_options_filter *filter, bool is_encoder)
+{
+ uint64_t ret;
+
+ switch (filter->id) {
+ case LZMA_FILTER_COPY:
+ case LZMA_FILTER_X86:
+ case LZMA_FILTER_POWERPC:
+ case LZMA_FILTER_IA64:
+ case LZMA_FILTER_ARM:
+ case LZMA_FILTER_ARMTHUMB:
+ case LZMA_FILTER_SPARC:
+ case LZMA_FILTER_DELTA:
+ // These don't require any significant amount of memory.
+ ret = 0;
+ break;
+
+ case LZMA_FILTER_SUBBLOCK:
+ if (is_encoder) {
+ const lzma_options_subblock *options = filter->options;
+ ret = options->subblock_data_size;
+ } else {
+ ret = 0;
+ }
+ break;
+
+#ifdef HAVE_FILTER_LZMA
+ case LZMA_FILTER_LZMA: {
+ const lzma_options_lzma *options = filter->options;
+
+ // Literal coder - this can be signficant if both values are
+ // big, or if sizeof(probability) is big.
+ ret = literal_states(options->literal_context_bits,
+ options->literal_pos_bits) * LIT_SIZE
+ * sizeof(probability);
+
+ // Dictionary base size
+ ret += options->dictionary_size;
+
+ if (is_encoder) {
+# ifdef HAVE_ENCODER
+ // This is rough, but should be accurate enough
+ // in practice.
+ ret += options->dictionary_size / 2;
+
+ uint32_t dummy1;
+ uint32_t dummy2;
+ uint32_t num_items;
+ if (lzma_lz_encoder_hash_properties(
+ options->match_finder,
+ options->dictionary_size,
+ &dummy1, &dummy2, &num_items))
+ return UINT64_MAX;
+
+ ret += (uint64_t)(num_items) * sizeof(uint32_t);
+# else
+ return UINT64_MAX;
+# endif
+ }
+
+ break;
+ }
+#endif
+
+ default:
+ return UINT64_MAX;
+ }
+
+ return ret;
+}
+
+
+extern LZMA_API uint32_t
+lzma_memory_usage(const lzma_options_filter *filters, lzma_bool is_encoder)
+{
+ uint64_t usage = 0;
+
+ for (size_t i = 0; filters[i].id != UINT64_MAX; ++i) {
+ const uint64_t ret = get_usage(filters + i, is_encoder);
+ if (ret == UINT64_MAX)
+ return UINT32_MAX;
+
+ usage += ret;
+ }
+
+ // Convert to mebibytes with rounding.
+ return usage / (1024 * 1024) + (usage % (1024 * 1024) >= 512 ? 1 : 0);
+}