surfaces-unies/src/darray.c

166 lines
6.0 KiB
C
Raw Permalink Normal View History

/**
* \file darray.c
2018-11-24 21:01:09 +00:00
* \brief Implémentation des fonctions pour le type \ref darray
*/
2018-10-31 08:56:24 +00:00
#include "darray.h"
#include <stdio.h>
#include <string.h>
/**
2018-11-24 21:01:09 +00:00
* `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
2018-11-24 21:01:09 +00:00
* tableau. Cela implique quun objet \ref darray ne peut contenir que des
* éléments du même type.
2018-11-24 20:58:55 +00:00
*
2018-11-24 21:41:29 +00:00
* \param[in] t_element_size Taille des objets stockés
2018-11-24 21:01:09 +00:00
* \return Pointeur sur le nouvel objet \ref darray
*/
darray *darrayNew(uint64_t t_element_size) {
2018-11-24 20:58:55 +00:00
darray *ret;
ret = (darray *)malloc(sizeof(darray));
ret->begin = NULL;
ret->end = ret->begin;
2018-11-03 15:35:06 +00:00
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`.
2018-11-24 20:58:55 +00:00
*
2018-11-24 21:41:29 +00:00
* \param[in] t_self Objet \ref darray dans lequel on souhaite insérer un nouvel
2018-11-24 20:58:55 +00:00
* élément
2018-11-24 21:41:29 +00:00
* \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;
2018-11-24 20:58:55 +00:00
int64_t pos_aux;
2018-11-03 15:35:06 +00:00
pos_aux = (char *)t_pos - (char *)t_self->begin;
if (darraySize(t_self) >= t_self->capacity) {
darrayExtend(t_self);
}
2018-11-03 15:35:06 +00:00
itr = (char *)t_self->begin + pos_aux;
memmove(itr + t_self->element_size, itr, ((char *)t_self->end - itr));
2018-11-03 15:35:06 +00:00
memcpy(itr, t_elem, t_self->element_size);
(*t_self).end = (char *)t_self->end + t_self->element_size;
}
2018-10-31 08:56:24 +00:00
/**
* Étend la capacité d'un \ref darray en réallouant sa mémoire, multipliant
2018-10-31 08:56:24 +00:00
* 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
*
2018-11-24 21:41:29 +00:00
* \param[in] t_self L'objet darray à étendre
2018-10-31 08:56:24 +00:00
*/
void darrayExtend(darray *t_self) {
2018-10-31 08:56:24 +00:00
void *new_array;
uint64_t size;
2018-11-03 15:35:06 +00:00
size = darraySize(t_self);
2018-10-31 08:56:24 +00:00
new_array =
2018-11-03 15:35:06 +00:00
realloc(t_self->begin, (darraySize(t_self) + 1) * t_self->element_size);
2018-10-31 08:56:24 +00:00
if (!new_array) {
fprintf(stderr, "Failed memory reallocation at %s:%d\nAborting...",
__FILE__, __LINE__ - 2);
exit(PTR_ERROR);
}
2018-11-03 15:35:06 +00:00
(*t_self).begin = new_array;
++(*t_self).capacity;
(*t_self).end = (char *)t_self->begin + size * t_self->element_size;
2018-10-31 08:56:24 +00:00
}
/**
* `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.
2018-11-24 20:58:55 +00:00
*
2018-11-24 21:41:29 +00:00
* \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) {
2018-11-03 15:35:06 +00:00
memmove(t_pos, (char *)t_pos + t_self->element_size,
(((char *)t_self->end - t_self->element_size) - (char *)t_pos));
2018-11-03 15:35:06 +00:00
(*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`.
2018-11-24 20:58:55 +00:00
*
2018-11-24 21:41:29 +00:00
* \param[out] t_self Objet \ref darray à la fin duquel on souhaite ajouter un
2018-11-24 20:58:55 +00:00
* nouvel élément
2018-11-24 21:41:29 +00:00
* \param[in] t_elem Élément que lon souhaite ajouter à la fin de `self`
*/
void darrayPushBack(darray *t_self, void *t_elem) {
2018-11-03 15:35:06 +00:00
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.
2018-11-24 20:58:55 +00:00
*
2018-11-24 21:41:29 +00:00
* \param[out] t_self Objet dont on souhaite supprimer le dernier élément
*/
2018-11-24 20:58:55 +00:00
void darrayPopBack(darray *t_self) {
2018-11-03 15:35:06 +00:00
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.
2018-11-24 20:58:55 +00:00
*
2018-11-24 21:41:29 +00:00
* \param[out] t_self Objet \ref darray à supprimer
*/
2018-11-24 20:58:55 +00:00
void darrayDelete(darray *t_self) {
2018-11-03 15:35:06 +00:00
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.
2018-11-24 20:58:55 +00:00
*
2018-11-24 21:41:29 +00:00
* \param[out] t_self Objet \ref darray dont on souhaite connaître le nombre
2018-11-24 20:58:55 +00:00
* 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) /
2018-11-03 15:35:06 +00:00
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`.
2018-11-24 21:41:29 +00:00
* \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
2018-11-24 20:58:55 +00:00
* \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) {
2018-11-24 20:58:55 +00:00
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;
2018-11-03 15:35:06 +00:00
itr = (char *)t_self->begin + t_idx * t_self->element_size;
return itr;
}