]> icculus.org git repositories - icculus/xz.git/blob - src/liblzma/common/vli_decoder.c
Imported to git.
[icculus/xz.git] / src / liblzma / common / vli_decoder.c
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 /// \file       vli_decoder.c
4 /// \brief      Decodes variable-length integers
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
22
23 extern LZMA_API lzma_ret
24 lzma_vli_decode(lzma_vli *restrict vli, size_t *restrict vli_pos,
25                 const uint8_t *restrict in, size_t *restrict in_pos,
26                 size_t in_size)
27 {
28         if (*vli > LZMA_VLI_VALUE_MAX || *vli_pos >= 9
29                         || (*vli >> (7 * *vli_pos)) != 0)
30                 return LZMA_PROG_ERROR;
31
32         if (*in_pos >= in_size)
33                 return LZMA_BUF_ERROR;
34
35         if (*vli_pos == 0) {
36                 *vli_pos = 1;
37
38                 if (in[*in_pos] <= 0x7F) {
39                         // Single-byte integer
40                         *vli = in[*in_pos];
41                         ++*in_pos;
42                         return LZMA_STREAM_END;
43                 }
44
45                 *vli = in[*in_pos] & 0x7F;
46                 ++*in_pos;
47         }
48
49         while (*in_pos < in_size) {
50                 // Read in the next byte.
51                 *vli |= (lzma_vli)(in[*in_pos] & 0x7F) << (*vli_pos * 7);
52                 ++*vli_pos;
53
54                 // Check if this is the last byte of a multibyte integer.
55                 if (in[*in_pos] & 0x80) {
56                         ++*in_pos;
57                         return LZMA_STREAM_END;
58                 }
59
60                 // Limit variable-length representation to nine bytes.
61                 if (*vli_pos == 9)
62                         return LZMA_DATA_ERROR;
63
64                 // Increment input position only when the byte was accepted.
65                 ++*in_pos;
66         }
67
68         return LZMA_OK;
69 }