/*
 * Copyright 2012-15 Advanced Micro Devices, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 * Authors: AMD
 *
 */

#include <linux/slab.h>

#include "dm_services.h"
#include "include/vector.h"

bool dal_vector_construct(
	struct vector *vector,
	struct dc_context *ctx,
	uint32_t capacity,
	uint32_t struct_size)
{
	vector->container = NULL;

	if (!struct_size || !capacity) {
		/* Container must be non-zero size*/
		BREAK_TO_DEBUGGER();
		return false;
	}

	vector->container = kcalloc(capacity, struct_size, GFP_KERNEL);
	if (vector->container == NULL)
		return false;
	vector->capacity = capacity;
	vector->struct_size = struct_size;
	vector->count = 0;
	vector->ctx = ctx;
	return true;
}

bool dal_vector_presized_costruct(
	struct vector *vector,
	struct dc_context *ctx,
	uint32_t count,
	void *initial_value,
	uint32_t struct_size)
{
	uint32_t i;

	vector->container = NULL;

	if (!struct_size || !count) {
		/* Container must be non-zero size*/
		BREAK_TO_DEBUGGER();
		return false;
	}

	vector->container = kcalloc(count, struct_size, GFP_KERNEL);

	if (vector->container == NULL)
		return false;

	/* If caller didn't supply initial value then the default
	 * of all zeros is expected, which is exactly what dal_alloc()
	 * initialises the memory to. */
	if (NULL != initial_value) {
		for (i = 0; i < count; ++i)
			memmove(
				vector->container + i * struct_size,
				initial_value,
				struct_size);
	}

	vector->capacity = count;
	vector->struct_size = struct_size;
	vector->count = count;
	return true;
}

struct vector *dal_vector_presized_create(
	struct dc_context *ctx,
	uint32_t size,
	void *initial_value,
	uint32_t struct_size)
{
	struct vector *vector = kzalloc(sizeof(struct vector), GFP_KERNEL);

	if (vector == NULL)
		return NULL;

	if (dal_vector_presized_costruct(
		vector, ctx, size, initial_value, struct_size))
		return vector;

	BREAK_TO_DEBUGGER();
	kfree(vector);
	return NULL;
}

struct vector *dal_vector_create(
	struct dc_context *ctx,
	uint32_t capacity,
	uint32_t struct_size)
{
	struct vector *vector = kzalloc(sizeof(struct vector), GFP_KERNEL);

	if (vector == NULL)
		return NULL;

	if (dal_vector_construct(vector, ctx, capacity, struct_size))
		return vector;

	BREAK_TO_DEBUGGER();
	kfree(vector);
	return NULL;
}

void dal_vector_destruct(
	struct vector *vector)
{
	kfree(vector->container);
	vector->count = 0;
	vector->capacity = 0;
}

void dal_vector_destroy(
	struct vector **vector)
{
	if (vector == NULL || *vector == NULL)
		return;
	dal_vector_destruct(*vector);
	kfree(*vector);
	*vector = NULL;
}

uint32_t dal_vector_get_count(
	const struct vector *vector)
{
	return vector->count;
}

void *dal_vector_at_index(
	const struct vector *vector,
	uint32_t index)
{
	if (vector->container == NULL || index >= vector->count)
		return NULL;
	return vector->container + (index * vector->struct_size);
}

bool dal_vector_remove_at_index(
	struct vector *vector,
	uint32_t index)
{
	if (index >= vector->count)
		return false;

	if (index != vector->count - 1)
		memmove(
			vector->container + (index * vector->struct_size),
			vector->container + ((index + 1) * vector->struct_size),
			(vector->count - index - 1) * vector->struct_size);
	vector->count -= 1;

	return true;
}

void dal_vector_set_at_index(
	const struct vector *vector,
	const void *what,
	uint32_t index)
{
	void *where = dal_vector_at_index(vector, index);

	if (!where) {
		BREAK_TO_DEBUGGER();
		return;
	}
	memmove(
		where,
		what,
		vector->struct_size);
}

static inline uint32_t calc_increased_capacity(
	uint32_t old_capacity)
{
	return old_capacity * 2;
}

bool dal_vector_insert_at(
	struct vector *vector,
	const void *what,
	uint32_t position)
{
	uint8_t *insert_address;

	if (vector->count == vector->capacity) {
		if (!dal_vector_reserve(
			vector,
			calc_increased_capacity(vector->capacity)))
			return false;
	}

	insert_address = vector->container + (vector->struct_size * position);

	if (vector->count && position < vector->count)
		memmove(
			insert_address + vector->struct_size,
			insert_address,
			vector->struct_size * (vector->count - position));

	memmove(
		insert_address,
		what,
		vector->struct_size);

	vector->count++;

	return true;
}

bool dal_vector_append(
	struct vector *vector,
	const void *item)
{
	return dal_vector_insert_at(vector, item, vector->count);
}

struct vector *dal_vector_clone(
	const struct vector *vector)
{
	struct vector *vec_cloned;
	uint32_t count;

	/* create new vector */
	count = dal_vector_get_count(vector);

	if (count == 0)
		/* when count is 0 we still want to create clone of the vector
		 */
		vec_cloned = dal_vector_create(
			vector->ctx,
			vector->capacity,
			vector->struct_size);
	else
		/* Call "presized create" version, independently of how the
		 * original vector was created.
		 * The owner of original vector must know how to treat the new
		 * vector - as "presized" or as "regular".
		 * But from vector point of view it doesn't matter. */
		vec_cloned = dal_vector_presized_create(vector->ctx, count,
			NULL,/* no initial value */
			vector->struct_size);

	if (NULL == vec_cloned) {
		BREAK_TO_DEBUGGER();
		return NULL;
	}

	/* copy vector's data */
	memmove(vec_cloned->container, vector->container,
			vec_cloned->struct_size * vec_cloned->capacity);

	return vec_cloned;
}

uint32_t dal_vector_capacity(const struct vector *vector)
{
	return vector->capacity;
}

bool dal_vector_reserve(struct vector *vector, uint32_t capacity)
{
	void *new_container;

	if (capacity <= vector->capacity)
		return true;

	new_container = krealloc(vector->container,
				 capacity * vector->struct_size, GFP_KERNEL);

	if (new_container) {
		vector->container = new_container;
		vector->capacity = capacity;
		return true;
	}

	return false;
}

void dal_vector_clear(struct vector *vector)
{
	vector->count = 0;
}
