aboutsummaryrefslogblamecommitdiff
path: root/src/liblzma/common/index.c
blob: 6816b37a63d37fefead969026c1e767bdff8768c (plain) (tree)











































































































































                                                                               
///////////////////////////////////////////////////////////////////////////////
//
/// \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;
}