aboutsummaryrefslogtreecommitdiff
path: root/src/liblzma/api/lzma/vli.h
blob: 322014e1dd350ccd1f7399eabff5783bc9c36e90 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
/**
 * \file        lzma/vli.h
 * \brief       Variable-length integer handling
 *
 * \author      Copyright (C) 1999-2006 Igor Pavlov
 * \author      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.
 */

#ifndef LZMA_H_INTERNAL
#	error Never include this file directly. Use <lzma.h> instead.
#endif


/**
 * \brief       Maximum supported value of variable-length integer
 */
#define LZMA_VLI_VALUE_MAX (UINT64_MAX / 2)

/**
 * \brief       VLI value to denote that the value is unknown
 */
#define LZMA_VLI_VALUE_UNKNOWN UINT64_MAX

/**
 * \brief       Maximum supported length of variable length integers
 */
#define LZMA_VLI_BYTES_MAX 9


/**
 * \brief       VLI constant suffix
 */
#define LZMA_VLI_C(n) UINT64_C(n)


/**
 * \brief       Variable-length integer type
 *
 * This will always be unsigned integer. Valid VLI values are in the range
 * [0, LZMA_VLI_VALUE_MAX]. Unknown value is indicated with
 * LZMA_VLI_VALUE_UNKNOWN, which is the maximum value of the underlaying
 * integer type (this feature is useful in several situations).
 *
 * In future, even if lzma_vli is typdefined to something else than uint64_t,
 * it is guaranteed that 2 * LZMA_VLI_VALUE_MAX will not overflow lzma_vli.
 * This simplifies integer overflow detection.
 */
typedef uint64_t lzma_vli;


/**
 * \brief       Simple macro to validate variable-length integer
 *
 * This is useful to test that application has given acceptable values
 * for example in the uncompressed_size and compressed_size variables.
 *
 * \return      True if the integer is representable as VLI or if it
 *              indicates unknown value.
 */
#define lzma_vli_is_valid(vli) \
	((vli) <= LZMA_VLI_VALUE_MAX || (vli) == LZMA_VLI_VALUE_UNKNOWN)


/**
 * \brief       Sets VLI to given value with error checking
 *
 * \param       dest    Target variable which must have type of lzma_vli.
 * \param       src     New value to be stored to dest.
 * \param       limit   Maximum allowed value for src.
 *
 * \return      False on success, true on error. If an error occurred,
 *              dest is left in undefined state (i.e. it's possible that
 *              it will be different in newer liblzma versions).
 */
#define lzma_vli_set_lim(dest, src, limit) \
	((src) > (limit) || ((dest) = (src)) > (limit))

/**
 * \brief
 */
#define lzma_vli_add_lim(dest, src, limit) \
	((src) > (limit) || ((dest) += (src)) > (limit))

#define lzma_vli_add2_lim(dest, src1, src2, limit) \
	(lzma_vli_add_lim(dest, src1, limit) \
		|| lzma_vli_add_lim(dest, src2, limit))

#define lzma_vli_add3_lim(dest, src1, src2, src3, limit) \
	(lzma_vli_add_lim(dest, src1, limit) \
		|| lzma_vli_add_lim(dest, src2, limit) \
		|| lzma_vli_add_lim(dest, src3, limit))

#define lzma_vli_add4_lim(dest, src1, src2, src3, src4, limit) \
	(lzma_vli_add_lim(dest, src1, limit) \
		|| lzma_vli_add_lim(dest, src2, limit) \
		|| lzma_vli_add_lim(dest, src3, limit) \
		|| lzma_vli_add_lim(dest, src4, limit))

#define lzma_vli_sum_lim(dest, src1, src2, limit) \
	(lzma_vli_set_lim(dest, src1, limit) \
		|| lzma_vli_add_lim(dest, src2, limit))

#define lzma_vli_sum3_lim(dest, src1, src2, src3, limit) \
	(lzma_vli_set_lim(dest, src1, limit) \
		|| lzma_vli_add_lim(dest, src2, limit) \
		|| lzma_vli_add_lim(dest, src3, limit))

#define lzma_vli_sum4_lim(dest, src1, src2, src3, src4, limit) \
	(lzma_vli_set_lim(dest, src1, limit) \
		|| lzma_vli_add_lim(dest, src2, limit) \
		|| lzma_vli_add_lim(dest, src3, limit) \
		|| lzma_vli_add_lim(dest, src4, limit))

#define lzma_vli_set(dest, src) lzma_vli_set_lim(dest, src, LZMA_VLI_VALUE_MAX)

#define lzma_vli_add(dest, src) lzma_vli_add_lim(dest, src, LZMA_VLI_VALUE_MAX)

#define lzma_vli_add2(dest, src1, src2) \
	lzma_vli_add2_lim(dest, src1, src2, LZMA_VLI_VALUE_MAX)

#define lzma_vli_add3(dest, src1, src2, src3) \
	lzma_vli_add3_lim(dest, src1, src2, src3, LZMA_VLI_VALUE_MAX)

#define lzma_vli_add4(dest, src1, src2, src3, src4) \
	lzma_vli_add4_lim(dest, src1, src2, src3, src4, LZMA_VLI_VALUE_MAX)

#define lzma_vli_sum(dest, src1, src2) \
	lzma_vli_sum_lim(dest, src1, src2, LZMA_VLI_VALUE_MAX)

#define lzma_vli_sum3(dest, src1, src2, src3) \
	lzma_vli_sum3_lim(dest, src1, src2, src3, LZMA_VLI_VALUE_MAX)

#define lzma_vli_sum4(dest, src1, src2, src3, src4) \
	lzma_vli_sum4_lim(dest, src1, src2, src3, src4, LZMA_VLI_VALUE_MAX)


/**
 * \brief       Encodes variable-length integer
 *
 * In the new .lzma format, most integers are encoded in variable-length
 * representation. This saves space when smaller values are more likely
 * than bigger values.
 *
 * The encoding scheme encodes seven bits to every byte, using minimum
 * number of bytes required to represent the given value. In other words,
 * it puts 7-63 bits into 1-9 bytes. This implementation limits the number
 * of bits used to 63, thus num must be at maximum of INT64_MAX / 2. You
 * may use LZMA_VLI_VALUE_MAX for clarity.
 *
 * \param       vli       Integer to be encoded
 * \param       vli_pos   How many bytes have already been written out. This
 *                        must be less than 9 before calling this function.
 * \param       vli_size  Minimum size that the variable-length representation
 *                        must take. This is useful if you want to use
 *                        variable-length integers as padding. Usually you want
 *                        to set this to zero. The maximum allowed value is 9.
 * \param       out       Beginning of the output buffer
 * \param       out_pos   The next byte will be written to out[*out_pos].
 * \param       out_size  Size of the out buffer; the first byte into
 *                        which no data is written to is out[out_size].
 *
 * \return      - LZMA_OK: So far all OK, but the integer is not
 *                completely written out yet.
 *              - LZMA_STREAM_END: Integer successfully encoded.
 *              - LZMA_BUF_ERROR: No output space (*out_pos == out_size)
 *              - LZMA_PROG_ERROR: Arguments are not sane.
 */
extern lzma_ret lzma_vli_encode(
		lzma_vli vli, size_t *lzma_restrict vli_pos, size_t vli_size,
		uint8_t *lzma_restrict out, size_t *lzma_restrict out_pos,
		size_t out_size);


/**
 * \brief       Decodes variable-length integer
 *
 * \param       vli       Pointer to decoded integer. The decoder will
 *                        initialize it to zero when *vli_pos == 0, so
 *                        application isn't required to initialize *vli.
 * \param       vli_pos   How many bytes have already been decoded. When
 *                        starting to decode a new integer, *vli_pos must
 *                        be initialized to zero.
 * \param       in        Beginning of the input buffer
 * \param       in_pos    The next byte will be read from in[*in_pos].
 * \param       in_size   Size of the input buffer; the first byte that
 *                        won't be read is in[in_size].
 *
 * \return      - LZMA_OK: So far all OK, but the integer is not
 *                completely decoded yet.
 *              - LZMA_STREAM_END: Integer successfully decoded.
 *              - LZMA_BUF_ERROR: No input data (*in_pos == in_size)
 *              - LZMA_DATA_ERROR: Integer is longer than nine bytes.
 *              - LZMA_PROG_ERROR: Arguments are not sane.
 */
extern lzma_ret lzma_vli_decode(lzma_vli *lzma_restrict vli,
		size_t *lzma_restrict vli_pos, const uint8_t *lzma_restrict in,
		size_t *lzma_restrict in_pos, size_t in_size);


/**
 * \brief       Decodes variable-length integer reading buffer backwards
 *
 * The variable-length integer encoding is designed so that it can be read
 * either from the beginning to the end, or from the end to the beginning.
 * This feature is needed to make the Stream parseable backwards;
 * specifically, to read the Backward Size field in Stream Footer.
 *
 * \param       vli       Pointer to variable to hold the decoded integer.
 * \param       in        Beginning of the input buffer
 * \param       in_size   Number of bytes available in the in[] buffer.
 *                        On successful decoding, this is updated to match
 *                        the number of bytes used. (in[*in_size - 1] is the
 *                        first byte to process. After successful decoding,
 *                        in[*in_size] will point to the first byte of the
 *                        variable-length integer.)
 *
 * \return      - LZMA_OK: Decoding successful
 *              - LZMA_DATA_ERROR: No valid variable-length integer was found.
 *              - LZMA_BUF_ERROR: Not enough input. Note that in practice,
 *                this tends to be a sign of broken input, because the
 *                applications usually do give as much input to this function
 *                as the applications have available.
 */
extern lzma_ret lzma_vli_reverse_decode(
		lzma_vli *vli, const uint8_t *in, size_t *in_size);


/**
 * \brief       Gets the minimum number of bytes required to encode vli
 *
 * \return      Number of bytes on success (1-9). If vli isn't valid,
 *              zero is returned.
 */
extern size_t lzma_vli_size(lzma_vli vli);