star-phor-input

File format for describing photoreactor configurations
git clone https://www.edstar.cnrs.fr/git/star-phor-input.git
Log | Files | Refs | README | LICENSE

commit fa06cc8e62d0a7e5e99613de06e6fd3255fc9a23
parent d31b4a80a95f36c06985aaf646fad80860b81c69
Author: Eduardo Fontana Lazzari <edufonlaz@gmail.com>
Date:   Wed, 26 Feb 2025 17:18:29 +0100

Implement sensor API and fix memory release in sphin_surface

The sphin_source structure, a member of sphin_surface, is now
reference-counted. When releasing sphin_surface, check if its
associated source is NULL. If not, decrement its reference counter.

Diffstat:
MMakefile | 1+
Msrc/sphin.h | 15++++++++++++++-
Asrc/sphin_sensor.c | 209+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/sphin_sensor.h | 40++++++++++++++++++++++++++++++++++++++++
Msrc/sphin_surface.c | 27+++++++++++++++++++++++----
Msrc/sphin_volume.c | 13++++++++++++-
6 files changed, 299 insertions(+), 6 deletions(-)

diff --git a/Makefile b/Makefile @@ -39,6 +39,7 @@ SRC = \ src/sphin_brdf.c \ src/sphin_config.c \ src/sphin_geometry.c \ + src/sphin_sensor.c \ src/sphin_source.c \ src/sphin_surface.c \ src/sphin_volume.c diff --git a/src/sphin.h b/src/sphin.h @@ -62,6 +62,7 @@ enum sphin_photon_unit { SPHIN_PHOTON_UNIT_NONE__ }; +/* TODO Maybe change this to source_surface* */ enum sphin_source_direction_distribution_type { SPHIN_SOURCE_DIRECTION_COLLIM, SPHIN_SOURCE_DIRECTION_COS_POW_N, @@ -143,6 +144,7 @@ static const struct sphin_source_direction_distribution struct sphin; /* Library handler */ struct sphin_brdf; struct sphin_config; /* Physical configuration */ +struct sphin_sensor; struct sphin_source; struct sphin_source_power; struct sphin_surface; @@ -272,7 +274,7 @@ sphin_source_get_power struct sphin_source_power* power); /******************************************************************************* - * API of the source + * API of the BRDF ******************************************************************************/ SPHIN_API res_T sphin_brdf_ref_get @@ -292,6 +294,17 @@ sphin_brdf_specular_get_reflectivity (struct sphin_brdf* brdf, double* reflectivity); +/******************************************************************************* + * API of the sensor + ******************************************************************************/ +SPHIN_API res_T +sphin_sensor_ref_get + (struct sphin_sensor* sensor); + +SPHIN_API res_T +sphin_sensor_ref_put + (struct sphin_sensor* sensor); + END_DECLS #endif /* SPHIN_H */ diff --git a/src/sphin_sensor.c b/src/sphin_sensor.c @@ -0,0 +1,209 @@ +/* Copyright (C) 2024 Centre National de la Recherche Scientifique + * Copyright (C) 2024 Clermont Auvergne INP + * Copyright (C) 2024 INSA Lyon + * Copyright (C) 2024 Institut Mines Télécom Albi-Carmaux + * Copyright (C) 2024 Institut National Polytechnique de Toulouse + * Copyright (C) 2024 |Méso|Star> (contact@meso-star.com) + * Copyright (C) 2024 PhotonLyX (info@photonlyx.com) + * Copyright (C) 2024 Université de Lorraine + * Copyright (C) 2024 Université Paul Sabatier + * Copyright (C) 2024 Université Toulouse - Jean Jaurès + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#define _POSIX_C_SOURCE 200112L /* for strtok_r support */ + +#include "sphin.h" +#include "sphin_c.h" +#include "sphin_config.h" +#include "sphin_sensor.h" + +#include <rsys/cstr.h> +#include <rsys/ref_count.h> +#include <rsys/str.h> +#include <rsys/text_reader.h> + +struct txtrdr; + +struct sphin_sensor { + struct str name; + double response_function; + struct sphin* sphin; + ref_T ref; +}; + +/******************************************************************************* + * Helper functions + ******************************************************************************/ +static res_T +sensor_create + (struct sphin* sphin, + const char* name, + struct sphin_sensor** out_sensor) +{ + struct sphin_sensor* sensor = NULL; + res_T res = RES_OK; + + ASSERT(NULL != sphin); + ASSERT(NULL != out_sensor); + ASSERT(NULL != name); + ASSERT('\0' != name[0]); /* Name can't be empty */ + + sensor = MEM_CALLOC(sphin->allocator, 1, sizeof(struct sphin_sensor)); + if (NULL == sensor) { res = RES_MEM_ERR; goto error; } + ref_init(&sensor->ref); + SPHIN(ref_get(sphin)); + sensor->sphin = sphin; + + str_init(sphin->allocator, &sensor->name); + res = str_set(&sensor->name, name); + if (RES_OK != res) { goto error; } + +exit: + *out_sensor = sensor; + return res; +error: + if (NULL != sensor) { + SPHIN(sensor_ref_put(sensor)); + sensor = NULL; + } + goto exit; +} + +static void +release_sensor(ref_T* address) +{ + struct sphin_sensor* sensor = NULL; + struct sphin* sphin = NULL; + + ASSERT(NULL != address); + + sensor = CONTAINER_OF(address, struct sphin_sensor, ref); + str_release(&sensor->name); + sphin = sensor->sphin; + MEM_RM(sphin->allocator, sensor); + SPHIN(ref_put(sphin)); +} + +static res_T +parse_response_function + (struct sphin_sensor* sensor, + struct txtrdr* txtrdr, + char* value) +{ + char* token = NULL; + char* token_ptr = NULL; + res_T res = RES_OK; + double response_function; + + ASSERT(NULL != sensor); + (void) txtrdr; /* Disable unused variable warning */ + + token = strtok_r(value, " \t", &token_ptr); + + res = cstr_to_double(token, &response_function); + if (RES_OK != res) { res = RES_BAD_ARG; goto error; } + if (response_function < 0) { res = RES_BAD_ARG; goto error; } + sensor->response_function = response_function; + + token = strtok_r(NULL, " \t", &token_ptr); + if (NULL != token) { res = RES_BAD_ARG; goto error; } + +exit: + return res; +error: + goto exit; +} + +/******************************************************************************* + * Local functions + ******************************************************************************/ +res_T +parse_sensor + (struct sphin* sphin, + struct txtrdr* txtrdr, + const char* name, + struct sphin_sensor** out_sensor) +{ + char* keyword; + char* token; + char* token_ptr; + char* value; + struct sphin_sensor* sensor; + struct str line; + res_T res = RES_OK; + + ASSERT(NULL != sphin); + + str_init(sphin->allocator, &line); + + res = sensor_create(sphin, name, &sensor); + if (RES_OK != res) { res = RES_BAD_ARG; goto error; } + + + while (NULL != txtrdr_get_line(txtrdr)) { + res = str_set(&line, txtrdr_get_cline(txtrdr)); + if (RES_OK != res) { goto error; } + + /* Parse keyword */ + token = strtok_r(str_get(&line), ":", &token_ptr); + if (NULL == token){ res = RES_BAD_ARG; goto error; } + keyword = trim_keyword(token); + if (NULL == keyword){ res = RES_BAD_ARG; goto error; } + + /* Parse value */ + token = strtok_r(NULL, "", &token_ptr); + if (NULL == token){ res = RES_BAD_ARG; goto error; } + value = token; + /* Parse response function */ + if (0 == strcmp(keyword, "response_function")){ + res = parse_response_function(sensor, txtrdr, value); + } + else { + break; + } + } + +exit: + *out_sensor = sensor; + return res; +error: + if (sensor != NULL){ + SPHIN(sensor_ref_put(sensor)); + sensor = NULL; + } + goto exit; +} + +/******************************************************************************* + * Exported functions + ******************************************************************************/ +res_T +sphin_sensor_ref_get(struct sphin_sensor* sensor) +{ + if (NULL == sensor) { + return RES_BAD_ARG; + } + ref_get(&sensor->ref); + return RES_OK; +} + +res_T +sphin_sensor_ref_put(struct sphin_sensor* sensor) +{ + if (NULL == sensor) { + return RES_BAD_ARG; + } + ref_put(&sensor->ref, release_sensor); + return RES_OK; +} diff --git a/src/sphin_sensor.h b/src/sphin_sensor.h @@ -0,0 +1,40 @@ +/* Copyright (C) 2024 Centre National de la Recherche Scientifique + * Copyright (C) 2024 Clermont Auvergne INP + * Copyright (C) 2024 INSA Lyon + * Copyright (C) 2024 Institut Mines Télécom Albi-Carmaux + * Copyright (C) 2024 Institut National Polytechnique de Toulouse + * Copyright (C) 2024 |Méso|Star> (contact@meso-star.com) + * Copyright (C) 2024 PhotonLyX (info@photonlyx.com) + * Copyright (C) 2024 Université de Lorraine + * Copyright (C) 2024 Université Paul Sabatier + * Copyright (C) 2024 Université Toulouse - Jean Jaurès + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef SPHIN_SOURCE_H +#define SPHIN_SOURCE_H + +#include <rsys/rsys.h> + +struct sphin_sensor; +struct txtrdr; + +extern LOCAL_SYM res_T +parse_sensor + (struct sphin* sphin, + struct txtrdr* txtrdr, + const char* name, + struct sphin_sensor** out_sensor); + +#endif /* SPHIN_SOURCE */ diff --git a/src/sphin_surface.c b/src/sphin_surface.c @@ -28,6 +28,7 @@ #include "sphin_c.h" #include "sphin_config.h" #include "sphin_geometry.h" +#include "sphin_sensor.h" #include "sphin_source.h" #include "sphin_surface.h" @@ -42,6 +43,7 @@ struct sphin_surface { struct sphin_brdf* brdf; struct darray_geometry geometries; /* dynamic array of struct geometry. see rsys/dynamic_array.h */ + struct sphin_sensor* sensor; struct sphin_source* source; ref_T ref; }; @@ -69,6 +71,8 @@ surface_create SPHIN(ref_get(sphin)); surface->sphin = sphin; surface->brdf = NULL; + surface->sensor = NULL; + surface->source = NULL; str_init(sphin->allocator, &surface->name); res = str_set(&surface->name, name); @@ -90,6 +94,8 @@ release_surface(ref_T* address) { struct sphin* sphin = NULL; struct sphin_brdf* brdf = NULL; + struct sphin_sensor* sensor =NULL; + struct sphin_source* source = NULL; struct sphin_surface* surface = NULL; ASSERT(NULL != address); @@ -97,9 +103,16 @@ release_surface(ref_T* address) str_release(&surface->name); sphin = surface->sphin; brdf = surface->brdf; - SPHIN(ref_put(sphin)); - SPHIN(brdf_ref_put(brdf)); + sensor = surface->sensor; + source = surface->source; MEM_RM(sphin->allocator, surface); + if (NULL != source) { + SPHIN(source_ref_put(source)); + } + if (NULL != sensor) { + SPHIN(sensor_ref_put(sensor)); + } + SPHIN(brdf_ref_put(brdf)); SPHIN(ref_put(sphin)); } @@ -181,7 +194,12 @@ parse_surface res = parse_brdf(surface->sphin, txtrdr, value, &surface->brdf); } else if (0 == strcmp(keyword, "source")) { - res = parse_source(surface->sphin, txtrdr, value, &surface->source); + value = trim_string(value); + // res = parse_source(surface->sphin, txtrdr, name, &surface->source); + } + else if (0 == strcmp(keyword, "sensor")) { + value = trim_string(value); + res = parse_sensor(surface->sphin, txtrdr, name, &surface->sensor); } else { break; @@ -242,6 +260,7 @@ sphin_surface_get_source if (NULL == surface || NULL == source) { return RES_BAD_ARG; } - *source = surface->source; + + *source = surface->source; /* NULL if surface has no source */ return RES_OK; } diff --git a/src/sphin_volume.c b/src/sphin_volume.c @@ -27,6 +27,7 @@ #include "sphin_c.h" #include "sphin_config.h" #include "sphin_geometry.h" +#include "sphin_sensor.h" #include "sphin_volume.h" #include <rsys/cstr.h> /* str_to_double */ @@ -39,6 +40,7 @@ struct sphin_volume { double ka; struct darray_geometry geometries; /* dynamic array of struct geometry. see rsys/dynamic_array.h */ + struct sphin_sensor* sensor; struct sphin* sphin; ref_T ref; }; @@ -65,6 +67,7 @@ volume_create ref_init(&volume->ref); SPHIN(ref_get(sphin)); volume->sphin = sphin; + volume->sensor = NULL; str_init(sphin->allocator, &volume->name); darray_geometry_init(sphin->allocator, &volume->geometries); @@ -87,14 +90,18 @@ release_volume(ref_T* address) { struct sphin_volume* volume = NULL; struct sphin* sphin = NULL; - + struct sphin_sensor* sensor = NULL; ASSERT(NULL != address); volume = CONTAINER_OF(address, struct sphin_volume, ref); str_release(&volume->name); darray_geometry_release(&volume->geometries); sphin = volume->sphin; + sensor = volume->sensor; MEM_RM(sphin->allocator, volume); + if (NULL != sensor) { + SPHIN(sensor_ref_put(sensor)); + } SPHIN(ref_put(sphin)); } @@ -205,6 +212,10 @@ parse_volume else if (0 == strcmp(keyword, "ka")){ res = parse_ka(volume, txtrdr, value); } + else if (0 == strcmp(keyword, "sensor")) { + value = trim_string(value); + res = parse_sensor(volume->sphin, txtrdr, name, &volume->sensor); + } else { break; }