| /////////////////////////////////////////////////////////////////////////////// |
| // |
| /// \file index.c |
| /// \brief Handling of Index in Metadata |
| // |
| // 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" |
| |
| |
| /** |
| * \brief Duplicates an Index list |
| * |
| * \return A copy of the Index list, or NULL if memory allocation |
| * failed or the original Index was empty. |
| */ |
| extern LZMA_API lzma_index * |
| lzma_index_dup(const lzma_index *old_current, lzma_allocator *allocator) |
| { |
| lzma_index *new_head = NULL; |
| lzma_index *new_current = NULL; |
| |
| while (old_current != NULL) { |
| lzma_index *i = lzma_alloc(sizeof(lzma_index), allocator); |
| if (i == NULL) { |
| lzma_index_free(new_head, allocator); |
| return NULL; |
| } |
| |
| i->total_size = old_current->total_size; |
| i->uncompressed_size = old_current->uncompressed_size; |
| i->next = NULL; |
| |
| if (new_head == NULL) |
| new_head = i; |
| else |
| new_current->next = i; |
| |
| new_current = i; |
| old_current = old_current->next; |
| } |
| |
| return new_head; |
| } |
| |
| |
| /** |
| * \brief Frees an Index list |
| * |
| * All Index Recors in the list are freed. This function is convenient when |
| * getting rid of lzma_metadata structures containing an Index. |
| */ |
| extern LZMA_API void |
| lzma_index_free(lzma_index *i, lzma_allocator *allocator) |
| { |
| while (i != NULL) { |
| lzma_index *tmp = i->next; |
| lzma_free(i, allocator); |
| i = tmp; |
| } |
| |
| return; |
| } |
| |
| |
| /** |
| * \brief Calculates properties of an Index list |
| * |
| * |
| */ |
| extern LZMA_API lzma_ret |
| lzma_index_count(const lzma_index *i, size_t *count, |
| lzma_vli *lzma_restrict total_size, |
| lzma_vli *lzma_restrict uncompressed_size) |
| { |
| *count = 0; |
| *total_size = 0; |
| *uncompressed_size = 0; |
| |
| while (i != NULL) { |
| if (i->total_size == LZMA_VLI_VALUE_UNKNOWN) { |
| *total_size = LZMA_VLI_VALUE_UNKNOWN; |
| } else if (i->total_size > LZMA_VLI_VALUE_MAX) { |
| return LZMA_PROG_ERROR; |
| } else if (*total_size != LZMA_VLI_VALUE_UNKNOWN) { |
| *total_size += i->total_size; |
| if (*total_size > LZMA_VLI_VALUE_MAX) |
| return LZMA_PROG_ERROR; |
| } |
| |
| if (i->uncompressed_size == LZMA_VLI_VALUE_UNKNOWN) { |
| *uncompressed_size = LZMA_VLI_VALUE_UNKNOWN; |
| } else if (i->uncompressed_size > LZMA_VLI_VALUE_MAX) { |
| return LZMA_PROG_ERROR; |
| } else if (*uncompressed_size != LZMA_VLI_VALUE_UNKNOWN) { |
| *uncompressed_size += i->uncompressed_size; |
| if (*uncompressed_size > LZMA_VLI_VALUE_MAX) |
| return LZMA_PROG_ERROR; |
| } |
| |
| ++*count; |
| i = i->next; |
| } |
| |
| // FIXME ? |
| if (*total_size == LZMA_VLI_VALUE_UNKNOWN |
| || *uncompressed_size == LZMA_VLI_VALUE_UNKNOWN) |
| return LZMA_HEADER_ERROR; |
| |
| return LZMA_OK; |
| } |
| |
| |
| |
| extern LZMA_API lzma_bool |
| lzma_index_is_equal(const lzma_index *a, const lzma_index *b) |
| { |
| while (a != NULL && b != NULL) { |
| if (a->total_size != b->total_size || a->uncompressed_size |
| != b->uncompressed_size) |
| return false; |
| |
| a = a->next; |
| b = b->next; |
| } |
| |
| return a == b; |
| } |