]> icculus.org git repositories - icculus/xz.git/blob - src/liblzma/common/memory_usage.c
Update the code to mostly match the new simpler file format
[icculus/xz.git] / src / liblzma / common / memory_usage.c
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 /// \file       memory_usage.c
4 /// \brief      Calculate rough amount of memory required by filters
5 //
6 //  Copyright (C) 2007 Lasse Collin
7 //
8 //  This library is free software; you can redistribute it and/or
9 //  modify it under the terms of the GNU Lesser General Public
10 //  License as published by the Free Software Foundation; either
11 //  version 2.1 of the License, or (at your option) any later version.
12 //
13 //  This library is distributed in the hope that it will be useful,
14 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 //  Lesser General Public License for more details.
17 //
18 ///////////////////////////////////////////////////////////////////////////////
19
20 #include "common.h"
21 #include "lz_encoder.h"
22 #include "lzma_literal.h"
23
24
25 static uint64_t
26 get_usage(const lzma_options_filter *filter, bool is_encoder)
27 {
28         uint64_t ret;
29
30         switch (filter->id) {
31         case LZMA_FILTER_X86:
32         case LZMA_FILTER_POWERPC:
33         case LZMA_FILTER_IA64:
34         case LZMA_FILTER_ARM:
35         case LZMA_FILTER_ARMTHUMB:
36         case LZMA_FILTER_SPARC:
37         case LZMA_FILTER_DELTA:
38                 // These don't require any significant amount of memory.
39                 ret = 0;
40                 break;
41
42         case LZMA_FILTER_SUBBLOCK:
43                 if (is_encoder) {
44                         const lzma_options_subblock *options = filter->options;
45                         ret = options->subblock_data_size;
46                 } else {
47                         ret = 0;
48                 }
49                 break;
50
51 #ifdef HAVE_FILTER_LZMA
52         case LZMA_FILTER_LZMA: {
53                 const lzma_options_lzma *options = filter->options;
54
55                 // Literal coder - this can be signficant if both values are
56                 // big, or if sizeof(probability) is big.
57                 ret = literal_states(options->literal_context_bits,
58                                 options->literal_pos_bits) * LIT_SIZE
59                                 * sizeof(probability);
60
61                 // Dictionary base size
62                 ret += options->dictionary_size;
63
64                 if (is_encoder) {
65 #       ifdef HAVE_ENCODER
66                         // This is rough, but should be accurate enough
67                         // in practice.
68                         ret += options->dictionary_size / 2;
69
70                         uint32_t dummy1;
71                         uint32_t dummy2;
72                         uint32_t num_items;
73                         if (lzma_lz_encoder_hash_properties(
74                                         options->match_finder,
75                                         options->dictionary_size,
76                                         &dummy1, &dummy2, &num_items))
77                                 return UINT64_MAX;
78
79                         ret += (uint64_t)(num_items) * sizeof(uint32_t);
80 #       else
81                         return UINT64_MAX;
82 #       endif
83                 }
84
85                 break;
86         }
87 #endif
88
89         default:
90                 return UINT64_MAX;
91         }
92
93         return ret;
94 }
95
96
97 extern LZMA_API uint32_t
98 lzma_memory_usage(const lzma_options_filter *filters, lzma_bool is_encoder)
99 {
100         uint64_t usage = 0;
101
102         for (size_t i = 0; filters[i].id != UINT64_MAX; ++i) {
103                 const uint64_t ret = get_usage(filters + i, is_encoder);
104                 if (ret == UINT64_MAX)
105                         return UINT32_MAX;
106
107                 usage += ret;
108         }
109
110         // Convert to mebibytes with rounding.
111         return usage / (1024 * 1024) + (usage % (1024 * 1024) >= 512 ? 1 : 0);
112 }