]> icculus.org git repositories - icculus/xz.git/blob - src/liblzma/common/vli_encoder.c
Imported to git.
[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 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, size_t vli_size,
25                 uint8_t *restrict out, size_t *restrict out_pos,
26                 size_t out_size)
27 {
28         if (vli > LZMA_VLI_VALUE_MAX || *vli_pos >= 9 || vli_size > 9
29                         || (vli != 0 && (vli >> (7 * *vli_pos)) == 0))
30                 return LZMA_PROG_ERROR;
31
32         if (*out_pos >= out_size)
33                 return LZMA_BUF_ERROR;
34
35         if (*vli_pos == 0) {
36                 *vli_pos = 1;
37
38                 if (vli <= 0x7F && *vli_pos >= vli_size) {
39                         // Single-byte integer
40                         out[(*out_pos)++] = vli;
41                         return LZMA_STREAM_END;
42                 }
43
44                 // First byte of a multibyte integer
45                 out[(*out_pos)++] = (vli & 0x7F) | 0x80;
46         }
47
48         while (*out_pos < out_size) {
49                 const lzma_vli b = vli >> (7 * *vli_pos);
50                 ++*vli_pos;
51
52                 if (b <= 0x7F && *vli_pos >= vli_size) {
53                         // Last byte of a multibyte integer
54                         out[(*out_pos)++] = (b & 0xFF) | 0x80;
55                         return LZMA_STREAM_END;
56                 }
57
58                 // Middle byte of a multibyte integer
59                 out[(*out_pos)++] = b & 0x7F;
60         }
61
62         // vli is not yet completely written out.
63         return LZMA_OK;
64 }
65
66
67 extern LZMA_API size_t
68 lzma_vli_size(lzma_vli vli)
69 {
70         if (vli > LZMA_VLI_VALUE_MAX)
71                 return 0;
72
73         size_t i = 0;
74         do {
75                 vli >>= 7;
76                 ++i;
77         } while (vli != 0);
78
79         assert(i <= 9);
80         return i;
81 }