minishell/src/env/env_manip.c

167 lines
4.6 KiB
C

/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* env_manip.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: jguelen <jguelen@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/03/19 17:55:24 by kcolin #+# #+# */
/* Updated: 2025/03/21 18:49:56 by jguelen ### ########.fr */
/* */
/* ************************************************************************** */
#include "env.h"
#include "env_convert.h"
#include "env_manip.h"
#include "libft.h"
#include "../ft_errno.h"
/*
** 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);
}
/*
** 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 (ft_strncmp((*env)->key, key, INT_MAX) == 0)
{
next = (*env)->next;
env_destroy_node(*env);
(*env) = next;
return ;
}
current = *env;
while (current->next)
{
if (ft_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 is null, both key and value are freed and NULL is returned.
** ft_errno is set to FT_EINVAL. We therefore allow for a value to be NULL.
**
** If key is an empty string, key and value are freed, ft_errno is set to
** FT_EBADID, and NULL is returned.
**
** If there is a failure allocating a new node, NULL is returned and ft_errno is
** set to FT_EERRNO (malloc would have set it to ENOMEM).
**
** Returns a pointer to the first element in the linked list, or NULL on error.
**
** Warning: does not check for validity of a key beyond what is described above.
**
** Implementation notes: free2 always returns NULL
**
** Note: once you pass a key to this function, if you pass it a second time, it
** will cause bad behaviour.
**
** Once you passed key and/or value to this function, env is the owner of these
** values and is responsible for freeing them. Do not pass multiple times the
** same pointers to this function!
*/
t_env *env_set_entry(t_env **env, char *key, char *value)
{
t_env *node;
if (key == NULL || value == NULL)
return (ft_errno(FT_EINVAL), free2(key, value));
if (*key == '\0')
return (ft_errno(FT_EBADID), free2(key, value));
node = env_find_node_bykey(*env, key);
if (node == NULL)
{
node = ft_calloc(1, sizeof(t_env));
if (!node)
return (ft_errno(FT_EERRNO), free2(key, value));
node->key = key;
node->value = value;
env_add_back(env, node);
}
else
{
free(node->value);
free(key);
node->value = value;
}
return (*env);
}
/*
** 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);
}