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:
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;
}