271 lines
7.0 KiB
C
271 lines
7.0 KiB
C
/* Freetype GL - A C OpenGL Freetype engine
|
|
*
|
|
* Distributed under the OSI-approved BSD 2-Clause License. See accompanying
|
|
* file `LICENSE` for more details.
|
|
*/
|
|
#include <assert.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include "vector.h"
|
|
|
|
// ------------------------------------------------------------- vector_new ---
|
|
vector_t *vector_new(size_t item_size)
|
|
{
|
|
vector_t *self = (vector_t *) malloc(sizeof(vector_t));
|
|
assert(item_size);
|
|
|
|
if (!self)
|
|
{
|
|
fprintf(stderr, "line %d: No more memory for allocating data\n",
|
|
__LINE__);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
self->item_size = item_size;
|
|
self->size = 0;
|
|
self->capacity = 1;
|
|
self->items = malloc(self->item_size * self->capacity);
|
|
return self;
|
|
}
|
|
|
|
// ---------------------------------------------------------- vector_delete ---
|
|
void vector_delete(vector_t *self)
|
|
{
|
|
assert(self);
|
|
|
|
free(self->items);
|
|
free(self);
|
|
}
|
|
|
|
// ------------------------------------------------------------- vector_get ---
|
|
const void *vector_get(const vector_t *self, size_t index)
|
|
{
|
|
assert(self);
|
|
assert(self->size);
|
|
assert(index < self->size);
|
|
|
|
return (char *) (self->items) + index * self->item_size;
|
|
}
|
|
|
|
// ----------------------------------------------------------- vector_front ---
|
|
const void *vector_front(const vector_t *self)
|
|
{
|
|
assert(self);
|
|
assert(self->size);
|
|
|
|
return vector_get(self, 0);
|
|
}
|
|
|
|
// ------------------------------------------------------------ vector_back ---
|
|
const void *vector_back(const vector_t *self)
|
|
{
|
|
assert(self);
|
|
assert(self->size);
|
|
|
|
return vector_get(self, self->size - 1);
|
|
}
|
|
|
|
// -------------------------------------------------------- vector_contains ---
|
|
int vector_contains(const vector_t *self, const void *item,
|
|
int (*cmp)(const void *, const void *))
|
|
{
|
|
size_t i;
|
|
assert(self);
|
|
|
|
for (i = 0; i < self->size; ++i)
|
|
{
|
|
if ((*cmp)(item, vector_get(self, i)) == 0)
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// ----------------------------------------------------------- vector_empty ---
|
|
int vector_empty(const vector_t *self)
|
|
{
|
|
assert(self);
|
|
|
|
return self->size == 0;
|
|
}
|
|
|
|
// ------------------------------------------------------------ vector_size ---
|
|
size_t vector_size(const vector_t *self)
|
|
{
|
|
assert(self);
|
|
|
|
return self->size;
|
|
}
|
|
|
|
// --------------------------------------------------------- vector_reserve ---
|
|
void vector_reserve(vector_t *self, const size_t size)
|
|
{
|
|
assert(self);
|
|
|
|
if (self->capacity < size)
|
|
{
|
|
self->items = realloc(self->items, size * self->item_size);
|
|
self->capacity = size;
|
|
}
|
|
}
|
|
|
|
// -------------------------------------------------------- vector_capacity ---
|
|
size_t vector_capacity(const vector_t *self)
|
|
{
|
|
assert(self);
|
|
|
|
return self->capacity;
|
|
}
|
|
|
|
// ---------------------------------------------------------- vector_shrink ---
|
|
void vector_shrink(vector_t *self)
|
|
{
|
|
assert(self);
|
|
|
|
if (self->capacity > self->size)
|
|
{
|
|
self->items = realloc(self->items, self->size * self->item_size);
|
|
}
|
|
self->capacity = self->size;
|
|
}
|
|
|
|
// ----------------------------------------------------------- vector_clear ---
|
|
void vector_clear(vector_t *self)
|
|
{
|
|
assert(self);
|
|
|
|
self->size = 0;
|
|
}
|
|
|
|
// ------------------------------------------------------------- vector_set ---
|
|
void vector_set(vector_t *self, const size_t index, const void *item)
|
|
{
|
|
assert(self);
|
|
assert(self->size);
|
|
assert(index < self->size);
|
|
|
|
memcpy((char *) (self->items) + index * self->item_size, item,
|
|
self->item_size);
|
|
}
|
|
|
|
// ---------------------------------------------------------- vector_insert ---
|
|
void vector_insert(vector_t *self, const size_t index, const void *item)
|
|
{
|
|
assert(self);
|
|
assert(index <= self->size);
|
|
|
|
if (self->capacity <= self->size)
|
|
{
|
|
vector_reserve(self, 2 * self->capacity);
|
|
}
|
|
if (index < self->size)
|
|
{
|
|
memmove((char *) (self->items) + (index + 1) * self->item_size,
|
|
(char *) (self->items) + (index + 0) * self->item_size,
|
|
(self->size - index) * self->item_size);
|
|
}
|
|
self->size++;
|
|
vector_set(self, index, item);
|
|
}
|
|
|
|
// ----------------------------------------------------- vector_erase_range ---
|
|
void vector_erase_range(vector_t *self, const size_t first, const size_t last)
|
|
{
|
|
assert(self);
|
|
assert(first < self->size);
|
|
assert(last < self->size + 1);
|
|
assert(first < last);
|
|
|
|
memmove((char *) (self->items) + first * self->item_size,
|
|
(char *) (self->items) + last * self->item_size,
|
|
(self->size - last) * self->item_size);
|
|
self->size -= (last - first);
|
|
}
|
|
|
|
// ----------------------------------------------------------- vector_erase ---
|
|
void vector_erase(vector_t *self, const size_t index)
|
|
{
|
|
assert(self);
|
|
assert(index < self->size);
|
|
|
|
vector_erase_range(self, index, index + 1);
|
|
}
|
|
|
|
// ------------------------------------------------------- vector_push_back ---
|
|
void vector_push_back(vector_t *self, const void *item)
|
|
{
|
|
vector_insert(self, self->size, item);
|
|
}
|
|
|
|
// -------------------------------------------------------- vector_pop_back ---
|
|
void vector_pop_back(vector_t *self)
|
|
{
|
|
assert(self);
|
|
assert(self->size);
|
|
|
|
self->size--;
|
|
}
|
|
|
|
// ---------------------------------------------------------- vector_resize ---
|
|
void vector_resize(vector_t *self, const size_t size)
|
|
{
|
|
assert(self);
|
|
|
|
if (size > self->capacity)
|
|
{
|
|
vector_reserve(self, size);
|
|
self->size = self->capacity;
|
|
}
|
|
else
|
|
{
|
|
self->size = size;
|
|
}
|
|
}
|
|
|
|
// -------------------------------------------------- vector_push_back_data ---
|
|
void vector_push_back_data(vector_t *self, const void *data, const size_t count)
|
|
{
|
|
assert(self);
|
|
assert(data);
|
|
assert(count);
|
|
|
|
if (self->capacity < (self->size + count))
|
|
{
|
|
vector_reserve(self, self->size + count);
|
|
}
|
|
memmove((char *) (self->items) + self->size * self->item_size, data,
|
|
count * self->item_size);
|
|
self->size += count;
|
|
}
|
|
|
|
// ----------------------------------------------------- vector_insert_data ---
|
|
void vector_insert_data(vector_t *self, const size_t index, const void *data,
|
|
const size_t count)
|
|
{
|
|
assert(self);
|
|
assert(index < self->size);
|
|
assert(data);
|
|
assert(count);
|
|
|
|
if (self->capacity < (self->size + count))
|
|
{
|
|
vector_reserve(self, self->size + count);
|
|
}
|
|
memmove((char *) (self->items) + (index + count) * self->item_size,
|
|
(char *) (self->items) + (index) *self->item_size,
|
|
count * self->item_size);
|
|
memmove((char *) (self->items) + index * self->item_size, data,
|
|
count * self->item_size);
|
|
self->size += count;
|
|
}
|
|
|
|
// ------------------------------------------------------------ vector_sort ---
|
|
void vector_sort(vector_t *self, int (*cmp)(const void *, const void *))
|
|
{
|
|
assert(self);
|
|
assert(self->size);
|
|
|
|
qsort(self->items, self->size, self->item_size, cmp);
|
|
}
|