1*3b35e7eeSXin LI // SPDX-License-Identifier: 0BSD 2*3b35e7eeSXin LI 381ad8388SMartin Matuska /////////////////////////////////////////////////////////////////////////////// 481ad8388SMartin Matuska // 581ad8388SMartin Matuska /// \file vli_encoder.c 681ad8388SMartin Matuska /// \brief Encodes variable-length integers 781ad8388SMartin Matuska // 881ad8388SMartin Matuska // Author: Lasse Collin 981ad8388SMartin Matuska // 1081ad8388SMartin Matuska /////////////////////////////////////////////////////////////////////////////// 1181ad8388SMartin Matuska 1281ad8388SMartin Matuska #include "common.h" 1381ad8388SMartin Matuska 1481ad8388SMartin Matuska 1581ad8388SMartin Matuska extern LZMA_API(lzma_ret) 1681ad8388SMartin Matuska lzma_vli_encode(lzma_vli vli, size_t *vli_pos, 1781ad8388SMartin Matuska uint8_t *restrict out, size_t *restrict out_pos, 1881ad8388SMartin Matuska size_t out_size) 1981ad8388SMartin Matuska { 2081ad8388SMartin Matuska // If we haven't been given vli_pos, work in single-call mode. 2181ad8388SMartin Matuska size_t vli_pos_internal = 0; 2281ad8388SMartin Matuska if (vli_pos == NULL) { 2381ad8388SMartin Matuska vli_pos = &vli_pos_internal; 2481ad8388SMartin Matuska 2581ad8388SMartin Matuska // In single-call mode, we expect that the caller has 2681ad8388SMartin Matuska // reserved enough output space. 2781ad8388SMartin Matuska if (*out_pos >= out_size) 2881ad8388SMartin Matuska return LZMA_PROG_ERROR; 2981ad8388SMartin Matuska } else { 3081ad8388SMartin Matuska // This never happens when we are called by liblzma, but 3181ad8388SMartin Matuska // may happen if called directly from an application. 3281ad8388SMartin Matuska if (*out_pos >= out_size) 3381ad8388SMartin Matuska return LZMA_BUF_ERROR; 3481ad8388SMartin Matuska } 3581ad8388SMartin Matuska 3681ad8388SMartin Matuska // Validate the arguments. 3781ad8388SMartin Matuska if (*vli_pos >= LZMA_VLI_BYTES_MAX || vli > LZMA_VLI_MAX) 3881ad8388SMartin Matuska return LZMA_PROG_ERROR; 3981ad8388SMartin Matuska 4081ad8388SMartin Matuska // Shift vli so that the next bits to encode are the lowest. In 4181ad8388SMartin Matuska // single-call mode this never changes vli since *vli_pos is zero. 4281ad8388SMartin Matuska vli >>= *vli_pos * 7; 4381ad8388SMartin Matuska 4481ad8388SMartin Matuska // Write the non-last bytes in a loop. 4581ad8388SMartin Matuska while (vli >= 0x80) { 4681ad8388SMartin Matuska // We don't need *vli_pos during this function call anymore, 4781ad8388SMartin Matuska // but update it here so that it is ready if we need to 4881ad8388SMartin Matuska // return before the whole integer has been decoded. 4981ad8388SMartin Matuska ++*vli_pos; 5081ad8388SMartin Matuska assert(*vli_pos < LZMA_VLI_BYTES_MAX); 5181ad8388SMartin Matuska 5281ad8388SMartin Matuska // Write the next byte. 5381ad8388SMartin Matuska out[*out_pos] = (uint8_t)(vli) | 0x80; 5481ad8388SMartin Matuska vli >>= 7; 5581ad8388SMartin Matuska 5681ad8388SMartin Matuska if (++*out_pos == out_size) 5781ad8388SMartin Matuska return vli_pos == &vli_pos_internal 5881ad8388SMartin Matuska ? LZMA_PROG_ERROR : LZMA_OK; 5981ad8388SMartin Matuska } 6081ad8388SMartin Matuska 6181ad8388SMartin Matuska // Write the last byte. 6281ad8388SMartin Matuska out[*out_pos] = (uint8_t)(vli); 6381ad8388SMartin Matuska ++*out_pos; 6481ad8388SMartin Matuska ++*vli_pos; 6581ad8388SMartin Matuska 6681ad8388SMartin Matuska return vli_pos == &vli_pos_internal ? LZMA_OK : LZMA_STREAM_END; 6781ad8388SMartin Matuska 6881ad8388SMartin Matuska } 69