surfaces-unies/src/darray.c
2018-11-21 10:46:01 +01:00

151 lines
5.8 KiB
C
Raw 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_t
*/
#include "darray.h"
#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 lespace mémoire à allouer à chacun des éléments dans le
* tableau. Cela implique quun objet \ref darray_t ne peut contenir que des
* éléments du même type.
* \param[in] element_size Taille des objets stockés
* \return Pointeur sur le nouvel objet \ref darray_t
*/
darray* darrayNew(size_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] self Objet \ref darray 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 lon souhaite insérer
*/
void darrayInsert(darray *t_self, void *t_pos, void *t_elem) {
char *itr;
long 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,
(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;
}
/**
* É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] self L'objet darray à étendre
*/
void darrayExtend(darray *t_self) {
void *new_array;
size_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] self Objet \ref `darray` dont on souhaite supprimer un élément
* \param[in] 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,
(unsigned long)(((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] self Objet \ref darray à la fin duquel on souhaite ajouter un nouvel élément
* \param[in] 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] 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] 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] self Objet \ref darray dont on souhaite connaître le nombre déléments
* \return Nombre déléments contenus dans `self`
*/
size_t darraySize(darray* t_self) {
return (size_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] self Objet \ref darray duquel on souhaite obtenir un pointeur sur lélément à lindex `idx`
* \param[in] 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, size_t t_idx) {
void *itr;
itr = (char *)t_self->begin + t_idx * t_self->element_size;
return itr;
}