blob: 6816b37a63d37fefead969026c1e767bdff8768c [file] [log] [blame]
///////////////////////////////////////////////////////////////////////////////
//
/// \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;
}