Merge branch 'vars' into dev

This commit is contained in:
william.valenduc 2026-01-19 18:21:13 +00:00
commit 4c7029ccc0
7 changed files with 367 additions and 27 deletions

View file

@ -86,10 +86,21 @@ static bool expand_var(char **str, size_t pos, const struct hash_map *vars)
size_t r = parse_var_name(*str + pos, &var_name);
if (r > 0 && var_name != NULL)
{
char *value = get_var_or_env(vars, var_name);
if (value == NULL)
// Undefined variable: expand to empty string
value = "";
char *value;
char rnd_str[10]; // max 5 digits + null terminator
if (strcmp(var_name, "RANDOM") == 0)
{
short rnd = short_random();
snprintf(rnd_str, 10, "%d", rnd);
value = rnd_str;
}
else
{
value = get_var_or_env(vars, var_name);
if (value == NULL)
// Undefined variable: expand to empty string
value = "";
}
char *p = insert_into(*str, value, pos, r);
free(var_name);

View file

@ -55,7 +55,7 @@ struct hash_map *hash_map_init(size_t size)
bool hash_map_insert(struct hash_map *hash_map, const char *key, void *value,
bool *updated)
{
if (hash_map == NULL || hash_map->size == 0 || key == NULL)
if (hash_map == NULL || hash_map->size == 0 || key == NULL || value == NULL)
return false;
size_t h = hash(key);
@ -71,6 +71,7 @@ bool hash_map_insert(struct hash_map *hash_map, const char *key, void *value,
if (strcmp(iter->key, key) == 0)
{
// update
free(iter->value);
iter->value = value;
if (updated)
*updated = true;
@ -96,16 +97,16 @@ bool hash_map_insert(struct hash_map *hash_map, const char *key, void *value,
return true;
}
void hash_map_free(struct hash_map *hash_map)
void hash_map_free(struct hash_map **hash_map)
{
struct pair_list *l;
struct pair_list *prev;
if (hash_map)
if (hash_map != NULL && *hash_map != NULL)
{
for (size_t i = 0; i < hash_map->size; i++)
for (size_t i = 0; i < (*hash_map)->size; i++)
{
l = hash_map->data[i];
l = (*hash_map)->data[i];
while (l != NULL)
{
prev = l;
@ -113,8 +114,8 @@ void hash_map_free(struct hash_map *hash_map)
destroy_pair_list(&prev);
}
}
free(hash_map->data);
free(hash_map);
free((*hash_map)->data);
free(*hash_map);
}
}

View file

@ -19,10 +19,23 @@ struct hash_map
struct hash_map *hash_map_init(size_t size);
/**
* @brief Inserts a key-value pair into the hash map. Key and value are expected
* to be on the heap and will be managed by the hash map. It means they are
* consumed by this function. If the key already exists, its value is updated
* and the key is not consumed so it must be freed by the caller.
*
* @param hash_map The hash map.
* @param key The key to insert.
* @param value The value to insert.
* @param updated If not NULL, set to true if the key was already present and
* updated, false if the key was newly inserted.
* @return true on success, false on failure.
*/
bool hash_map_insert(struct hash_map *hash_map, const char *key, void *value,
bool *updated);
void hash_map_free(struct hash_map *hash_map);
void hash_map_free(struct hash_map **hash_map);
void hash_map_foreach(struct hash_map *hash_map,
void (*fn)(const char *, const void *));

View file

@ -2,8 +2,11 @@
#include "vars.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "../hash_map/hash_map.h"
@ -14,6 +17,26 @@ struct hash_map *vars_init(void)
return hash_map_init(VARS_INITIAL_SIZE);
}
void vars_default(struct hash_map *vars)
{
set_var_copy(vars, "?", "0");
pid_t pid = getpid();
char pid_str[20];
snprintf(pid_str, sizeof(pid_str), "%d", pid);
set_var_copy(vars, "$", pid_str);
}
short short_random(void)
{
static bool seeded = false;
if (!seeded)
{
srand((unsigned)time(NULL));
seeded = true;
}
return (short)(rand() & 0x7FFF); // force 16 bits positive
}
char *get_var(const struct hash_map *vars, const char *key)
{
return (char *)hash_map_get(vars, key);
@ -27,14 +50,21 @@ char *get_var_or_env(const struct hash_map *vars, const char *key)
return value;
}
bool set_var(struct hash_map *vars, const char *key, const char *value)
bool set_var(struct hash_map *vars, const char *key, const char *value,
bool *updated)
{
if (key == NULL || value == NULL)
return false;
return hash_map_insert(vars, key, (void *)value, NULL);
return hash_map_insert(vars, key, (void *)value, updated);
}
bool set_var_copy(struct hash_map *vars, const char *key, const char *value)
{
return set_var(vars, strdup(key), strdup(value));
char *key_copy = strdup(key);
char *value_copy = strdup(value);
bool updated;
bool res = set_var(vars, key_copy, value_copy, &updated);
if (updated || !res)
free(key_copy);
if (!res)
free(value_copy);
return res;
}

View file

@ -10,6 +10,16 @@
*/
struct hash_map *vars_init(void);
/**
* Set default variables.
*/
void vars_default(struct hash_map *vars);
/**
* Generate a random short integer (16 bits positive [0-32767]).
*/
short short_random(void);
/**
* Get the value of a variable, NULL if not found.
*/
@ -26,7 +36,8 @@ char *get_var_or_env(const struct hash_map *vars, const char *key);
* the hash_map and need to be on the heap. Returns true on success, false on
* failure.
*/
bool set_var(struct hash_map *vars, const char *key, const char *value);
bool set_var(struct hash_map *vars, const char *key, const char *value,
bool *updated);
/**
* Same as set_var, but makes copies of key and value so you don't have to worry