ENV: A small set of functions for internal env

This commit is contained in:
Jérôme Guélen 2025-02-16 13:07:33 +01:00 committed by Khaïs COLIN
parent 18a2835a7c
commit 660d785237
8 changed files with 447 additions and 41 deletions

View file

@ -6,7 +6,7 @@
/* By: jguelen <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/02/14 18:43:38 by jguelen #+# #+# */
/* Updated: 2025/02/18 16:23:24 by khais ### ########.fr */
/* Updated: 2025/02/18 16:33:10 by khais ### ########.fr */
/* */
/* ************************************************************************** */
@ -66,3 +66,18 @@ char *envp_get_val(char *line)
val_pointer++;
return (ft_strdup(val_pointer));
}
/*
** Get the value corresponding to a given key in the given environment structure
**
** If not found, return null
*/
char *env_get_val(t_env *env, char *key)
{
t_env *node;
node = env_find_node_bykey(env, key);
if (node)
return (node->value);
return (NULL);
}

178
src/env_manip.c Normal file
View file

@ -0,0 +1,178 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* env_manip.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: jguelen <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/02/12 18:29:12 by jguelen #+# #+# */
/* Updated: 2025/02/18 18:41:30 by khais ### ########.fr */
/* */
/* ************************************************************************** */
#include "env_manip.h"
#include "libft.h"
/*
** Remove the first env node of the given linked list where the key matches the
** given key.
**
** In any given env linked list, there should only be one entry for a given key.
**
** If the linked list is empty or the pointer is NULL, nothing is done.
**
** If the linked list does not contain an element matching the given key,
** nothing is done.
*/
void env_rm_entry(t_env **env, char *key)
{
t_env *current;
t_env *next;
if (env == NULL || (*env) == NULL)
return ;
if (strncmp((*env)->key, key, INT_MAX) == 0)
{
next = (*env)->next;
env_destroy_node(*env);
(*env) = next;
return ;
}
current = *env;
while (current->next)
{
if (strncmp(current->next->key, key, INT_MAX) == 0)
{
next = current->next;
current->next = next->next;
env_destroy_node(next);
return ;
}
current = current->next;
}
}
/*
** Add the given element to the end of the given linked list.
*/
static void env_add_back(t_env **env, t_env *new)
{
t_env *last;
last = *env;
if (last == NULL)
{
*env = new;
return ;
}
while (last->next)
last = last->next;
last->next = new;
}
/*
** In the given env linked list, if an element with the given key exist, set its
** value to the one provided. If no such element exist, create a new one with
** the provided value.
**
** The provided key and value must be allocated. In case of error, they will be
** freed. In case a node matching the given key is found the provided key value
** is freed.
**
** If key or value are null, both are freed and NULL is returned.
**
** If key is an empty string, key and value is freed and a non-error value is
** returned.
**
** If there is a failure allocating a new node, NULL is returned.
**
** Returns a pointer to the first element in the linked list, or NULL on error.
*/
t_env *env_set_entry(t_env **env, char *key, char *value)
{
t_env *node;
if (key == NULL || value == NULL)
return (free(key), free(value), NULL);
if (*key == '\0')
return (free(key), free(value), *env);
node = env_find_node_bykey(*env, key);
if (node == NULL)
{
node = ft_calloc(1, sizeof(t_env));
if (!node)
return (free(key), free(value), NULL);
node->key = key;
node->value = value;
env_add_back(env, node);
}
else
{
free(node->value);
free(key);
node->value = value;
}
return (*env);
}
/*
** read an envp structure, and create a t_env linked list containing the same
** information.
**
** the envp structure is not freed.
**
** in case of error, all memory is freed and null is returned.
**
** no checks additional checks than those of envp_get_key and envp_get_val are
** performed
*/
t_env *env_from_envp(char **envp)
{
t_env *env;
env = NULL;
while (*envp)
{
if (env_set_entry(&env, envp_get_key(*envp),
envp_get_val(*envp)) == NULL)
{
env_destroy(env);
return (NULL);
}
envp++;
}
return (env);
}
/*
** Create an envp structure from the given env linked list.
**
** The linked list is not destroyed.
**
** in case of allocation error, all memory is freed and NULL is returned.
*/
char **envp_from_env(t_env *env)
{
char **new_envp;
size_t size;
size_t i;
size = env_get_size(env);
new_envp = ft_calloc(size + 1, sizeof(char *));
if (new_envp == NULL)
return (NULL);
i = 0;
while (i < size)
{
new_envp[i] = ft_strjoin_sepc(env->key, env->value, '=');
if (new_envp[i] == NULL)
{
envp_destroy(new_envp);
return (NULL);
}
i++;
env = env->next;
}
new_envp[size] = NULL;
return (new_envp);
}

View file

@ -6,7 +6,7 @@
/* By: jguelen <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/02/14 13:46:39 by jguelen #+# #+# */
/* Updated: 2025/02/16 12:55:27 by jguelen ### ########.fr */
/* Updated: 2025/02/18 16:47:34 by khais ### ########.fr */
/* */
/* ************************************************************************** */
@ -36,8 +36,8 @@ t_env *env_from_envp(char **envp);
/*env_manip_utils*/
size_t env_get_size(t_env *env);
void env_destroy_node(t_env *node);
void env_destroy(t_env **env);
void envp_destroy_envp(char **envp);
void env_destroy(t_env *env);
void envp_destroy(char **envp);
t_env *env_find_node_bykey(t_env *env, char *key);
#endif

97
src/env_manip_utils.c Normal file
View file

@ -0,0 +1,97 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* env_manip_utils.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: jguelen <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/02/14 18:31:38 by jguelen #+# #+# */
/* Updated: 2025/02/18 16:40:32 by khais ### ########.fr */
/* */
/* ************************************************************************** */
#include "env_manip.h"
#include "libft.h"
/*
** Free all memory related to a given envp structure
*/
void envp_destroy(char **envp)
{
int i;
if (!envp)
return ;
i = 0;
while (envp[i])
{
free(envp[i]);
i++;
}
free(envp);
}
/*
** Free the given env node.
*/
void env_destroy_node(t_env *env)
{
if (!env)
return ;
free(env->key);
free(env->value);
free(env);
}
/*
** Free the given env linked list.
*/
void env_destroy(t_env *env)
{
t_env *next;
if (!env)
return ;
while (env)
{
next = env->next;
env_destroy_node(env);
env = next;
}
}
/*
** Get the number of mappings in the givne env linked list
*/
size_t env_get_size(t_env *env)
{
size_t nb_elem;
nb_elem = 0;
while (env)
{
nb_elem++;
env = env->next;
}
return (nb_elem);
}
/*
** Find and return a pointer to the node in the given env linked list where the
** key matches the given key.
**
** If the node is not found, return NULL.
**
** Note that this is a pointer to the middle of the linked list, the node is not
** copied.
*/
t_env *env_find_node_bykey(t_env *env, char *key)
{
while (env)
{
if (ft_strncmp(env->key, key, INT_MAX) == 0)
return (env);
env = env->next;
}
return (NULL);
}