| /////////////////////////////////////////////////////////////////////////////// |
| // |
| /// \file vli_decoder.c |
| /// \brief Decodes variable-length integers |
| // |
| // 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. |
| // |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| #include "common.h" |
| |
| |
| extern LZMA_API lzma_ret |
| lzma_vli_decode(lzma_vli *restrict vli, size_t *restrict vli_pos, |
| const uint8_t *restrict in, size_t *restrict in_pos, |
| size_t in_size) |
| { |
| if (*vli > LZMA_VLI_VALUE_MAX || *vli_pos >= 9 |
| || (*vli >> (7 * *vli_pos)) != 0) |
| return LZMA_PROG_ERROR; |
| |
| if (*in_pos >= in_size) |
| return LZMA_BUF_ERROR; |
| |
| if (*vli_pos == 0) { |
| *vli_pos = 1; |
| |
| if (in[*in_pos] <= 0x7F) { |
| // Single-byte integer |
| *vli = in[*in_pos]; |
| ++*in_pos; |
| return LZMA_STREAM_END; |
| } |
| |
| *vli = in[*in_pos] & 0x7F; |
| ++*in_pos; |
| } |
| |
| while (*in_pos < in_size) { |
| // Read in the next byte. |
| *vli |= (lzma_vli)(in[*in_pos] & 0x7F) << (*vli_pos * 7); |
| ++*vli_pos; |
| |
| // Check if this is the last byte of a multibyte integer. |
| if (in[*in_pos] & 0x80) { |
| ++*in_pos; |
| return LZMA_STREAM_END; |
| } |
| |
| // Limit variable-length representation to nine bytes. |
| if (*vli_pos == 9) |
| return LZMA_DATA_ERROR; |
| |
| // Increment input position only when the byte was accepted. |
| ++*in_pos; |
| } |
| |
| return LZMA_OK; |
| } |