surfaces-unies/src/darray.c

166 lines
6.0 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* \file darray.c
* \brief Implémentation des fonctions pour le type \ref darray
*/
#include "darray.h"
#include <stdio.h>
#include <string.h>
/**
* `darrayNew` permet de créer un nouvel objet de type \ref darray ne
* contenant aucun élément. Le seul paramètre, `element_size`, est utilisé afin
* de connaître lespace mémoire à allouer à chacun des éléments dans le
* tableau. Cela implique quun objet \ref darray ne peut contenir que des
* éléments du même type.
*
* \param[in] t_element_size Taille des objets stockés
* \return Pointeur sur le nouvel objet \ref darray
*/
darray *darrayNew(uint64_t t_element_size) {
darray *ret;
ret = (darray *)malloc(sizeof(darray));
ret->begin = NULL;
ret->end = ret->begin;
ret->element_size = t_element_size;
ret->capacity = 0;
return ret;
}
/**
* `darrayInsert` insère lélément `elem` avant l'élément pointé par `pos` dans
* lobjet \ref darray. Cela décalera tous les éléments stockés dans \a `self`
* pen dun cran vers la fin du tableau et insérera à lendroit pointé le nouvel
* élément. Cette fonction modifie les membres `begin` et `end` et
* potentiellement `capacity` de `self`.
*
* \param[in] t_self Objet \ref darray dans lequel on souhaite insérer un nouvel
* élément
* \param[in] t_pos Position à laquelle on souhaite insérer un nouvel élément
* \param[in] t_elem Élément que lon souhaite insérer
*/
void darrayInsert(darray *t_self, void *t_pos, void *t_elem) {
char *itr;
int64_t pos_aux;
pos_aux = (char *)t_pos - (char *)t_self->begin;
if (darraySize(t_self) >= t_self->capacity) {
darrayExtend(t_self);
}
itr = (char *)t_self->begin + pos_aux;
memmove(itr + t_self->element_size, itr, ((char *)t_self->end - itr));
memcpy(itr, t_elem, t_self->element_size);
(*t_self).end = (char *)t_self->end + t_self->element_size;
}
/**
* Étend la capacité d'un \ref darray en réallouant sa mémoire, multipliant
* sa capacité par deux. Si la réallocation mémoire ne réussit pas, le
* programme sarrête immédiatement, renvoyant la valeur de \ref PTR_ERROR
*
* \param[in] t_self L'objet darray à étendre
*/
void darrayExtend(darray *t_self) {
void *new_array;
uint64_t size;
size = darraySize(t_self);
new_array =
realloc(t_self->begin, (darraySize(t_self) + 1) * t_self->element_size);
if (!new_array) {
fprintf(stderr, "Failed memory reallocation at %s:%d\nAborting...",
__FILE__, __LINE__ - 2);
exit(PTR_ERROR);
}
(*t_self).begin = new_array;
++(*t_self).capacity;
(*t_self).end = (char *)t_self->begin + size * t_self->element_size;
}
/**
* `darrayErase` supprime lélément de objet \ref darray `self` pointé par
* `pos`. Cela décalera tous les éléments suivants dans le tableau dun cran
* vers le début du tableau de manière à ce quil ny aie pas délément vide
* entre les membres `begin` et `end` de `self`. Par ailleurs, le membre `end`
* de `self` se retrouve modifié par la fonction.
*
* \param[out] t_self Objet \ref darray dont on souhaite supprimer un élément
* \param[in] t_pos Élément de `self` que lon souhaite supprimer
*/
void darrayErase(darray *t_self, void *t_pos) {
memmove(t_pos, (char *)t_pos + t_self->element_size,
(((char *)t_self->end - t_self->element_size) - (char *)t_pos));
(*t_self).end = (char *)t_self->end - t_self->element_size;
}
/**
* `darrayPushBack` ajoute un nouvel élément `elem` à lobjet `self` à la fin du
* tableau de ce dernier. Cette fonction modifie le membre `end` de `self`.
*
* \param[out] t_self Objet \ref darray à la fin duquel on souhaite ajouter un
* nouvel élément
* \param[in] t_elem Élément que lon souhaite ajouter à la fin de `self`
*/
void darrayPushBack(darray *t_self, void *t_elem) {
darrayInsert(t_self, t_self->end, t_elem);
}
/**
* `darrayPopBack` permet de supprimer le dernier élément de lobjet \ref
* darray passé en argument. Cette fonction modifie le membre `end` de ce
* dernier objet.
*
* \param[out] t_self Objet dont on souhaite supprimer le dernier élément
*/
void darrayPopBack(darray *t_self) {
darrayErase(t_self, (char *)t_self->end - t_self->element_size);
}
/**
* `darrayDelete` supprime tous les éléments contenus par lobjet \ref darray
* passé en argument avant de libérer la mémoire occupée par lobjet lui-même.
* Lobjet passé en argument ne sera plus utilisable après utilisation de cette
* fonction.
*
* \param[out] t_self Objet \ref darray à supprimer
*/
void darrayDelete(darray *t_self) {
free(t_self->begin);
free(t_self);
}
/**
* `darraySize` renvoie le nombre déléments contenu dans le \ref darray
* `self` passé en arguments. Cette fonction ne modifie pas lélément passé en
* argument.
*
* \param[out] t_self Objet \ref darray dont on souhaite connaître le nombre
* déléments
* \return Nombre déléments contenus dans `self`
*/
uint64_t darraySize(darray *t_self) {
return (uint64_t)((char *)t_self->end - (char *)t_self->begin) /
t_self->element_size;
}
/**
* `darrayGet` permet de récupérer un élément dun objet \ref darray grâce à
* son index dans le tableau de lobjet `self`. Si lindex est trop grand, alors
* le pointeur `NULL` sera renvoyé, sinon un pointeur de type `void*` pointant
* sur lélément correspondant sera renvoyé. Cette fonction ne modifie pas
* lobjet `self`.
* \param[out] t_self Objet \ref darray duquel on souhaite obtenir un pointeur
* sur lélément à lindex `idx`
* \param[in] t_idx Index de lélément que lon souhaite récupérer
* \return Pointeur de type `void*` pointant sur lélément si lindex est
* valide, sur NULL sinon.
*/
void *darrayGet(darray *t_self, uint64_t t_idx) {
if (t_idx >= darraySize(t_self)) {
fprintf(stderr, "Error in `darrayGet`, out of bound idx: %zu (max: %zu)\n",
t_idx, darraySize(t_self));
exit(PTR_ERROR);
}
void *itr;
itr = (char *)t_self->begin + t_idx * t_self->element_size;
return itr;
}