]> icculus.org git repositories - icculus/xz.git/blob - src/liblzma/common/vli_encoder.c
VLI encoder and decoder cleanups. Made encoder return
[icculus/xz.git] / src / liblzma / common / vli_encoder.c
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 /// \file       vli_encoder.c
4 /// \brief      Encodes variable-length integers
5 //
6 //  Copyright (C) 2007-2008 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_encode(lzma_vli vli, size_t *restrict vli_pos,
25                 uint8_t *restrict out, size_t *restrict out_pos,
26                 size_t out_size)
27 {
28         // If we haven't been given vli_pos, work in single-call mode.
29         size_t vli_pos_internal = 0;
30         if (vli_pos == NULL) {
31                 vli_pos = &vli_pos_internal;
32
33                 // In single-call mode, we expect that the caller has
34                 // reserved enough output space.
35                 if (*out_pos >= out_size)
36                         return LZMA_PROG_ERROR;
37         } else {
38                 // This never happens when we are called by liblzma, but
39                 // may happen if called directly from an application.
40                 if (*out_pos >= out_size)
41                         return LZMA_BUF_ERROR;
42         }
43
44         // Validate the arguments.
45         if (*vli_pos >= LZMA_VLI_BYTES_MAX || vli > LZMA_VLI_MAX)
46                 return LZMA_PROG_ERROR;
47
48         // Shift vli so that the next bits to encode are the lowest. In
49         // single-call mode this never changes vli since *vli_pos is zero.
50         vli >>= *vli_pos * 7;
51
52         // Write the non-last bytes in a loop.
53         while (vli >= 0x80) {
54                 // We don't need *vli_pos during this function call anymore,
55                 // but update it here so that it is ready if we need to
56                 // return before the whole integer has been decoded.
57                 ++*vli_pos;
58                 assert(*vli_pos < LZMA_VLI_BYTES_MAX);
59
60                 // Write the next byte.
61                 out[*out_pos] = (uint8_t)(vli) | 0x80;
62                 vli >>= 7;
63
64                 if (++*out_pos == out_size)
65                         return vli_pos == &vli_pos_internal
66                                         ? LZMA_PROG_ERROR : LZMA_OK;
67         }
68
69         // Write the last byte.
70         out[*out_pos] = (uint8_t)(vli);
71         ++*out_pos;
72         ++*vli_pos;
73
74         return vli_pos == &vli_pos_internal ? LZMA_OK : LZMA_STREAM_END;
75
76 }