2018-10-21 19:42:58 +00:00
|
|
|
|
/**
|
|
|
|
|
* \file darray.c
|
|
|
|
|
* \brief Implémentation des fonctions pour le type \ref darray_t
|
|
|
|
|
*/
|
|
|
|
|
|
2018-10-31 08:56:24 +00:00
|
|
|
|
#include "darray.h"
|
2018-10-21 19:42:58 +00:00
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* `darrayNew` permet de créer un nouvel objet de type \ref darray_t ne
|
|
|
|
|
* contenant aucun élément. Le seul paramètre, `element_size`, est utilisé afin
|
|
|
|
|
* de connaître l’espace mémoire à allouer à chacun des éléments dans le
|
|
|
|
|
* tableau. Cela implique qu’un objet \ref darray_t ne peut contenir que des
|
|
|
|
|
* éléments du même type.
|
2018-11-06 15:08:20 +00:00
|
|
|
|
* \param[in] element_size Taille des objets stockés
|
2018-10-21 19:42:58 +00:00
|
|
|
|
* \return Pointeur sur le nouvel objet \ref darray_t
|
|
|
|
|
*/
|
2018-11-03 15:35:06 +00:00
|
|
|
|
darray_t darrayNew(size_t t_element_size) {
|
|
|
|
|
darray_t ret;
|
|
|
|
|
ret = (darray_t)malloc(sizeof(darray_t));
|
2018-10-21 19:42:58 +00:00
|
|
|
|
ret->begin = NULL;
|
|
|
|
|
ret->end = ret->begin;
|
2018-11-03 15:35:06 +00:00
|
|
|
|
ret->element_size = t_element_size;
|
2018-10-21 19:42:58 +00:00
|
|
|
|
ret->capacity = 0;
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* `darrayInsert` insère l’élément `elem` avant l'élément pointé par `pos` dans
|
|
|
|
|
* l’objet \ref darray_t. Cela décalera tous les éléments stockés dans \a `self`
|
|
|
|
|
* pen d’un cran vers la fin du tableau et insérera à l’endroit pointé le nouvel
|
|
|
|
|
* élément. Cette fonction modifie les membres `begin` et `end` et
|
|
|
|
|
* potentiellement `capacity` de `self`.
|
2018-11-06 15:08:20 +00:00
|
|
|
|
* \param[in] self Objet \ref darray_t dans lequel on souhaite insérer un nouvel élément
|
|
|
|
|
* \param[in] pos Position à laquelle on souhaite insérer un nouvel élément
|
|
|
|
|
* \param[in] elem Élément que l’on souhaite insérer
|
2018-10-21 19:42:58 +00:00
|
|
|
|
*/
|
2018-11-03 15:35:06 +00:00
|
|
|
|
void darrayInsert(darray_t t_self, void *t_pos, void *t_elem) {
|
2018-10-21 19:42:58 +00:00
|
|
|
|
char *itr;
|
2018-10-31 08:56:24 +00:00
|
|
|
|
long 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-10-21 19:42:58 +00:00
|
|
|
|
}
|
2018-11-03 15:35:06 +00:00
|
|
|
|
itr = (char *)t_self->begin + pos_aux;
|
|
|
|
|
memmove(itr + t_self->element_size, itr,
|
|
|
|
|
(unsigned long)((char *)t_self->end - itr));
|
|
|
|
|
memcpy(itr, t_elem, t_self->element_size);
|
|
|
|
|
(*t_self).end = (char *)t_self->end + t_self->element_size;
|
2018-10-21 19:42:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-10-31 08:56:24 +00:00
|
|
|
|
/**
|
|
|
|
|
* Étend la capacité d'un \ref darray_t en réallouant sa mémoire, multipliant
|
|
|
|
|
* sa capacité par deux. Si la réallocation mémoire ne réussit pas, le
|
|
|
|
|
* programme s’arrête immédiatement, renvoyant la valeur de \ref PTR_ERROR
|
|
|
|
|
*
|
2018-11-06 15:08:20 +00:00
|
|
|
|
* \param[in] self L'objet darray_t à étendre
|
2018-10-31 08:56:24 +00:00
|
|
|
|
*/
|
2018-11-03 15:35:06 +00:00
|
|
|
|
void darrayExtend(darray_t t_self) {
|
2018-10-31 08:56:24 +00:00
|
|
|
|
void *new_array;
|
|
|
|
|
size_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
|
|
|
|
}
|
|
|
|
|
|
2018-10-21 19:42:58 +00:00
|
|
|
|
/**
|
|
|
|
|
* `darrayErase` supprime l’élément de objet \ref darray_t `self` pointé par
|
|
|
|
|
* `pos`. Cela décalera tous les éléments suivants dans le tableau d’un cran
|
|
|
|
|
* vers le début du tableau de manière à ce qu’il n’y 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-06 15:08:20 +00:00
|
|
|
|
* \param[out] self Objet \ref `darray_t` dont on souhaite supprimer un élément
|
|
|
|
|
* \param[in] pos Élément de `self` que l’on souhaite supprimer
|
2018-10-21 19:42:58 +00:00
|
|
|
|
*/
|
2018-11-03 15:35:06 +00:00
|
|
|
|
void darrayErase(darray_t t_self, void *t_pos) {
|
|
|
|
|
memmove(t_pos, (char *)t_pos + t_self->element_size,
|
|
|
|
|
(unsigned long)(((char *)t_self->end - t_self->element_size) -
|
|
|
|
|
(char *)t_pos));
|
|
|
|
|
(*t_self).end = (char *)t_self->end - t_self->element_size;
|
2018-10-21 19:42:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* `darrayPushBack` ajoute un nouvel élément `elem` à l’objet `self` à la fin du
|
|
|
|
|
* tableau de ce dernier. Cette fonction modifie le membre `end` de `self`.
|
2018-11-06 15:08:20 +00:00
|
|
|
|
* \param[out] self Objet \ref darray_t à la fin duquel on souhaite ajouter un nouvel élément
|
|
|
|
|
* \param[in] elem Élément que l’on souhaite ajouter à la fin de `self`
|
2018-10-21 19:42:58 +00:00
|
|
|
|
*/
|
2018-11-03 15:35:06 +00:00
|
|
|
|
void darrayPushBack(darray_t t_self, void *t_elem) {
|
|
|
|
|
darrayInsert(t_self, t_self->end, t_elem);
|
2018-10-21 19:42:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* `darrayPopBack` permet de supprimer le dernier élément de l’objet \ref
|
|
|
|
|
* darray_t passé en argument. Cette fonction modifie le membre `end` de ce
|
|
|
|
|
* dernier objet.
|
2018-11-06 15:08:20 +00:00
|
|
|
|
* \param[out] self Objet dont on souhaite supprimer le dernier élément
|
2018-10-21 19:42:58 +00:00
|
|
|
|
*/
|
2018-11-03 15:35:06 +00:00
|
|
|
|
void darrayPopBack(darray_t t_self) {
|
|
|
|
|
darrayErase(t_self, (char *)t_self->end - t_self->element_size);
|
2018-10-21 19:42:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* `darrayDelete` supprime tous les éléments contenus par l’objet \ref darray_t
|
|
|
|
|
* passé en argument avant de libérer la mémoire occupée par l’objet lui-même.
|
|
|
|
|
* L’objet passé en argument ne sera plus utilisable après utilisation de cette
|
|
|
|
|
* fonction.
|
2018-11-06 15:08:20 +00:00
|
|
|
|
* \param[out] self Objet \ref darray_t à supprimer
|
2018-10-21 19:42:58 +00:00
|
|
|
|
*/
|
2018-11-03 15:35:06 +00:00
|
|
|
|
void darrayDelete(darray_t t_self) {
|
|
|
|
|
free(t_self->begin);
|
|
|
|
|
free(t_self);
|
2018-10-21 19:42:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* `darraySize` renvoie le nombre d’éléments contenu dans le \ref darray_t
|
|
|
|
|
* `self` passé en arguments. Cette fonction ne modifie pas l’élément passé en
|
|
|
|
|
* argument.
|
2018-11-06 15:08:20 +00:00
|
|
|
|
* \param[out] self Objet \ref darray_t dont on souhaite connaître le nombre d’éléments
|
2018-10-21 19:42:58 +00:00
|
|
|
|
* \return Nombre d’éléments contenus dans `self`
|
|
|
|
|
*/
|
2018-11-03 15:35:06 +00:00
|
|
|
|
size_t darraySize(darray_t t_self) {
|
|
|
|
|
return (size_t)((char *)t_self->end - (char *)t_self->begin) /
|
|
|
|
|
t_self->element_size;
|
2018-10-21 19:42:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* `darrayGet` permet de récupérer un élément d’un objet \ref darray_t grâce à
|
|
|
|
|
* son index dans le tableau de l’objet `self`. Si l’index 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
|
|
|
|
|
* l’objet `self`.
|
2018-11-06 15:08:20 +00:00
|
|
|
|
* \param[out] self Objet \ref darray_t duquel on souhaite obtenir un pointeur sur l’élément à l’index `idx`
|
|
|
|
|
* \param[in] idx Index de l’élément que l’on souhaite récupérer
|
2018-10-21 19:42:58 +00:00
|
|
|
|
* \return Pointeur de type `void*` pointant sur l’élément si l’index est valide, sur NULL sinon.
|
|
|
|
|
*/
|
2018-11-03 15:35:06 +00:00
|
|
|
|
void *darrayGet(darray_t t_self, size_t t_idx) {
|
2018-10-21 19:42:58 +00:00
|
|
|
|
void *itr;
|
2018-11-03 15:35:06 +00:00
|
|
|
|
itr = (char *)t_self->begin + t_idx * t_self->element_size;
|
2018-10-21 19:42:58 +00:00
|
|
|
|
return itr;
|
|
|
|
|
}
|