/*
 * Copyright (C) 2016 Google Inc.
 * Dan Cross <crossd@gmail.com>
 * See LICENSE for license details.
 */

#include <kmalloc.h>
#include <assert.h>
#include <error.h>
#include <slice.h>

void slice_init(struct slice *slice)
{
	memset(slice, 0, sizeof(*slice));
}

void slice_clear(struct slice *slice)
{
	slice->len = 0;
	memset(slice->ptrs, 0, sizeof(*slice->ptrs) * slice->capacity);
}

void *slice_get(struct slice *slice, size_t i)
{
	if (i >= slice->len)
		return NULL;
	return slice->ptrs[i];
}

bool slice_put(struct slice *slice, size_t i, void *p)
{
	if (i >= slice->len)
		return FALSE;
	slice->ptrs[i] = p;
	return TRUE;
}

bool slice_del(struct slice *slice, size_t i)
{
	if (i >= slice->len)
		return FALSE;
	memmove(slice->ptrs + i, slice->ptrs + i + 1,
	        (slice->len - (i + 1)) * sizeof(void *));
	slice->len--;
	return TRUE;
}

void slice_append(struct slice *s, void *p)
{
	void **ps;

	assert(p != NULL);
	if (s->len == s->capacity) {
		if (s->capacity == 0)
			s->capacity = 4;
		s->capacity *= 2;
		ps = kreallocarray(s->ptrs, s->capacity, sizeof(void *),
				   MEM_WAIT);
		assert(ps != NULL); /* XXX: if size*sizeof(void*) overflows. */
		s->ptrs = ps;
	}
	s->ptrs[s->len] = p;
	s->len++;
}

size_t slice_len(struct slice *slice)
{
	return slice->len;
}

void **slice_finalize(struct slice *slice)
{
	void **ps;

	ps = kreallocarray(slice->ptrs, slice->len, sizeof(void *), MEM_WAIT);
	assert(ps != NULL);
	slice->len = 0;
	slice->capacity = 0;
	slice->ptrs = NULL;

	return ps;
}

void slice_destroy(struct slice *slice)
{
	kfree(slice->ptrs);
	slice->ptrs = NULL;
	slice->capacity = 0;
	slice->len = 0;
}
