sphin_volume.c (11286B)
1 /* Copyright (C) 2024-2026 Centre National de la Recherche Scientifique 2 * Copyright (C) 2024-2026 Clermont Auvergne INP 3 * Copyright (C) 2024-2026 INSA Lyon 4 * Copyright (C) 2024-2026 Institut Mines Télécom Albi-Carmaux 5 * Copyright (C) 2024-2026 Institut National Polytechnique de Toulouse 6 * Copyright (C) 2024-2026 |Méso|Star> (contact@meso-star.com) 7 * Copyright (C) 2024-2026 PhotonLyX (info@photonlyx.com) 8 * Copyright (C) 2024-2026 Université de Lorraine 9 * Copyright (C) 2024-2026 Université Paul Sabatier 10 * Copyright (C) 2024-2026 Université Toulouse - Jean Jaurès 11 * 12 * This program is free software: you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License as published by 14 * the Free Software Foundation, either version 3 of the License, or 15 * (at your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU General Public License for more details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with this program. If not, see <http://www.gnu.org/licenses/>. */ 24 #define _POSIX_C_SOURCE 200112L /* for strtok_r support */ 25 26 #include "sphin.h" 27 #include "sphin_c.h" 28 #include "sphin_config.h" 29 #include "sphin_geometry.h" 30 #include "sphin_prop_rad.h" 31 #include "sphin_refractive_index.h" 32 #include "sphin_sensor_volume.h" 33 #include "sphin_volume.h" 34 35 #include <rsys/mem_allocator.h> 36 #include <rsys/ref_count.h> 37 #include <rsys/rsys.h> 38 #include <rsys/str.h> 39 #include <rsys/text_reader.h> 40 41 struct sphin_sensor_volume; 42 43 /******************************************************************************* 44 * Helper functions 45 ******************************************************************************/ 46 static res_T 47 volume_create 48 (struct sphin* sphin, 49 const char* name, 50 struct sphin_volume** out_volume) 51 { 52 struct sphin_volume* volume = NULL; 53 res_T res = RES_OK; 54 55 ASSERT(NULL != sphin); 56 ASSERT(NULL != out_volume); 57 ASSERT(NULL != name); 58 ASSERT('\0' != name[0]); /* Name can't be empty */ 59 60 volume = MEM_CALLOC(sphin->allocator, 1, sizeof(struct sphin_volume)); 61 if (NULL == volume) { res = RES_MEM_ERR; goto error; } 62 63 /* Init volume ref counter and init member variables */ 64 ref_init(&volume->ref); 65 SPHIN(ref_get(sphin)); 66 volume->sphin = sphin; 67 volume->sensor_volume = NULL; 68 volume->refractive_index = NULL; 69 70 str_init(sphin->allocator, &volume->name); 71 darray_sphin_geometry_ptr_init(sphin->allocator, &volume->geometries); 72 darray_sphin_prop_rad_ptr_init(sphin->allocator, &volume->prop_rads); 73 res = str_set(&volume->name, name); 74 if (RES_OK != res) { goto error; } 75 76 exit: 77 *out_volume = volume; 78 return res; 79 error: 80 if (NULL != volume) { 81 SPHIN(volume_ref_put(volume)); 82 volume = NULL; 83 } 84 goto exit; 85 } 86 87 static void 88 release_volume 89 (ref_T* address) 90 { 91 size_t i, ngeometries, nprop_rads; 92 struct sphin_geometry** geometries = NULL; 93 struct sphin_prop_rad** prop_rads = NULL; 94 struct sphin* sphin = NULL; 95 struct sphin_sensor_volume* sensor_volume = NULL; 96 struct sphin_refractive_index* refr_ind = NULL; 97 struct sphin_volume* volume = NULL; 98 ASSERT(NULL != address); 99 100 volume = CONTAINER_OF(address, struct sphin_volume, ref); 101 str_release(&volume->name); 102 103 /* Retrieve the number of geometries and prop rads associated with the volume 104 * and decrease the reference counter of each one of them */ 105 ngeometries = darray_sphin_geometry_ptr_size_get(&volume->geometries); 106 geometries = darray_sphin_geometry_ptr_data_get(&volume->geometries); 107 108 nprop_rads = darray_sphin_prop_rad_ptr_size_get(&volume->prop_rads); 109 prop_rads = darray_sphin_prop_rad_ptr_data_get(&volume->prop_rads); 110 111 /* Put references for each one of the geometries */ 112 FOR_EACH(i, 0, ngeometries) { 113 SPHIN(geometry_ref_put(geometries[i])); 114 } 115 if (NULL != geometries) { 116 darray_sphin_geometry_ptr_release(&volume->geometries); 117 } 118 119 FOR_EACH(i, 0, nprop_rads) { 120 SPHIN(prop_rad_ref_put(prop_rads[i])); 121 } 122 if (NULL != prop_rads) { 123 darray_sphin_prop_rad_ptr_release(&volume->prop_rads); 124 } 125 sensor_volume = volume->sensor_volume; 126 if (NULL != sensor_volume) { 127 SPHIN(sensor_volume_ref_put(sensor_volume)); 128 } 129 refr_ind = volume->refractive_index; 130 if (NULL != refr_ind) { 131 SPHIN(refractive_index_ref_put(refr_ind)); 132 } 133 sphin = volume->sphin; 134 MEM_RM(sphin->allocator, volume); 135 SPHIN(ref_put(sphin)); 136 } 137 138 static res_T 139 parse_geometry 140 (struct sphin_volume* volume, 141 struct txtrdr* txtrdr, 142 char* value) 143 { 144 struct sphin_geometry* geom; 145 res_T res = RES_OK; 146 147 ASSERT(NULL != volume); 148 ASSERT(NULL != txtrdr); 149 150 if (NULL == value){ res = RES_BAD_ARG; goto error; } 151 152 res = geometry_parse(volume->sphin, value, &geom); 153 if (RES_OK != res) { goto error; } 154 155 /* Append a new element to the end of the volume->geometries dynamic array */ 156 res = darray_sphin_geometry_ptr_push_back(&volume->geometries, &geom); 157 if (RES_OK != res) { goto error; } 158 159 res = txtrdr_read_line(txtrdr); 160 if (RES_OK != res) { goto error; } 161 162 exit: 163 return res; 164 error: 165 goto exit; 166 } 167 168 /******************************************************************************* 169 * Local functions 170 ******************************************************************************/ 171 res_T 172 parse_volume 173 (struct sphin_config* config, 174 struct txtrdr* txtrdr, 175 const char* name) 176 { 177 struct sphin_volume* volume = NULL; 178 struct str line; 179 char* keyword = NULL; 180 char* token = NULL; 181 char* token_ptr = NULL; 182 res_T res = RES_OK; 183 184 ASSERT(NULL != config); 185 ASSERT(NULL != txtrdr); 186 ASSERT(NULL != name); 187 ASSERT('\0' != name[0]); /* Name can't be empty */ 188 189 str_init(config->sphin->allocator, &line); 190 191 res = volume_create(config->sphin, name, &volume); 192 if (RES_OK != res) { goto error; } 193 194 res = txtrdr_read_line(txtrdr); 195 if (RES_OK != res) { goto error; } 196 197 while (NULL != txtrdr_get_line(txtrdr)) { 198 res = str_set(&line, txtrdr_get_cline(txtrdr)); 199 if (RES_OK != res) { goto error; } 200 /* parse keyword */ 201 token = strtok_r(str_get(&line), ":", &token_ptr); 202 if (NULL == token){ res = RES_BAD_ARG; goto error; } 203 keyword = trim_keyword(token); 204 if (NULL == keyword){ res = RES_BAD_ARG; goto error; } 205 206 /* parse value */ 207 token = token_ptr; 208 if (0 == strcmp(keyword, "geometry")){ 209 res = parse_geometry(volume, txtrdr, token); 210 } 211 else if (0 == strcmp(keyword, "prop_rad")){ 212 res = parse_prop_rad(config, volume, txtrdr, token); 213 } 214 else if (0 == strcmp(keyword, "sensor")) { 215 /* for the sensor_volume, 216 * strings are not allowed in the input file after the ":" 217 * check if there is only tabs and spaces after ":" and return an error if 218 * not */ 219 token = strtok_r(NULL, "\t ", &token_ptr); 220 if (NULL != token) { res = RES_BAD_ARG; goto error; } 221 /* continue parsing otherwise */ 222 res = parse_sensor_volume 223 (volume->sphin, txtrdr, name, &volume->sensor_volume); 224 } 225 else if (0 == strcmp(keyword, "refractive_index")) { 226 /* for the sensor_volume, 227 * strings are not allowed in the input file after the ":" 228 * check if there is only tabs and spaces after ":" and return an error if 229 * not */ 230 token = strtok_r(NULL, "\t ", &token_ptr); 231 if (NULL != token) { res = RES_BAD_ARG; goto error; } 232 /* continue parsing otherwise */ 233 res = parse_refractive_index 234 (volume->sphin, txtrdr, &volume->refractive_index); 235 } 236 else { 237 break; 238 } 239 if (RES_OK != res) { goto error; } 240 } 241 242 /* Append a new element to the end of the sphin_config->volumes array */ 243 res = darray_sphin_volume_ptr_push_back(&config->volumes, &volume); 244 if (RES_OK != res) { goto error; } 245 246 exit: 247 str_release(&line); 248 return res; 249 error: 250 if (NULL != volume) { 251 SPHIN(volume_ref_put(volume)); 252 volume = NULL; 253 } 254 goto exit; 255 } 256 257 /******************************************************************************* 258 * Exported functions 259 ******************************************************************************/ 260 res_T 261 sphin_volume_ref_get 262 (struct sphin_volume* volume) 263 { 264 if (NULL == volume) { 265 return RES_BAD_ARG; 266 } 267 ref_get(&volume->ref); 268 return RES_OK; 269 } 270 271 res_T 272 sphin_volume_ref_put 273 (struct sphin_volume* volume) 274 { 275 if (NULL == volume) { 276 return RES_BAD_ARG; 277 } 278 ref_put(&volume->ref, release_volume); 279 return RES_OK; 280 } 281 282 res_T 283 sphin_volume_get_name 284 (struct sphin_volume* volume, 285 char** name) 286 { 287 if (NULL == volume || NULL == name) { 288 return RES_BAD_ARG; 289 } 290 *name = (char*)str_get((struct str*)&volume->name); 291 return RES_OK; 292 } 293 294 res_T 295 sphin_volume_compute_total_size 296 (struct sphin_volume* volume, 297 double* total_size) 298 { 299 double total_vol = 0.; 300 size_t geometry_count = 0; 301 size_t i = 0; 302 struct sphin_geometry* geometry = NULL; 303 304 if (NULL == volume) { return RES_BAD_ARG; } 305 if (NULL == total_size) { return RES_BAD_ARG; } 306 307 geometry_count = darray_sphin_geometry_ptr_size_get(&volume->geometries); 308 309 FOR_EACH(i, 0, geometry_count) { 310 geometry = darray_sphin_geometry_ptr_data_get(&volume->geometries)[i]; 311 total_vol += geometry_compute_volume(geometry, geometry->side); 312 } 313 *total_size = total_vol; 314 return RES_OK; 315 } 316 317 res_T 318 sphin_volume_get_sensor 319 (struct sphin_volume* volume, 320 struct sphin_sensor_volume** sensor_volume) 321 { 322 if (NULL == volume 323 || NULL == sensor_volume) { 324 return RES_BAD_ARG; 325 } 326 *sensor_volume = volume->sensor_volume; 327 return RES_OK; 328 } 329 330 res_T 331 sphin_volume_get_geometry_count 332 (struct sphin_volume* volume, 333 size_t* ngeometries) 334 { 335 if (NULL == volume || NULL == ngeometries) { 336 return RES_BAD_ARG; 337 } 338 339 *ngeometries = darray_sphin_geometry_ptr_size_get(&volume->geometries); 340 341 return RES_OK; 342 } 343 344 res_T 345 sphin_volume_get_geometry 346 (struct sphin_volume* volume, 347 size_t igeometry, 348 struct sphin_geometry** geometry) 349 { 350 size_t ngeometries; 351 if (NULL == volume) { 352 return RES_BAD_ARG; 353 } 354 355 ngeometries = darray_sphin_geometry_ptr_size_get(&volume->geometries); 356 if (igeometry > ngeometries) { 357 return RES_BAD_ARG; 358 } 359 360 *geometry = darray_sphin_geometry_ptr_data_get 361 (&volume->geometries)[igeometry]; 362 363 return RES_OK; 364 } 365 366 res_T 367 sphin_volume_get_prop_rad_count 368 (struct sphin_volume* volume, 369 size_t* prop_rad_count) 370 { 371 if (NULL == volume || NULL == prop_rad_count) { 372 return RES_BAD_ARG; 373 } 374 375 *prop_rad_count = darray_sphin_prop_rad_ptr_size_get(&volume->prop_rads); 376 377 return RES_OK; 378 } 379 380 res_T 381 sphin_volume_get_prop_rad 382 (struct sphin_volume* volume, 383 size_t iprop_rad, 384 struct sphin_prop_rad** prop_rad) 385 { 386 size_t prop_rad_count; 387 if (NULL == volume || NULL == prop_rad) { 388 return RES_BAD_ARG; 389 } 390 391 prop_rad_count = darray_sphin_prop_rad_ptr_size_get(&volume->prop_rads); 392 if (iprop_rad > prop_rad_count) { 393 return RES_BAD_ARG; 394 } 395 396 *prop_rad = darray_sphin_prop_rad_ptr_data_get(&volume->prop_rads)[iprop_rad]; 397 398 return RES_OK; 399 } 400 401 res_T 402 sphin_volume_get_refractive_index 403 (struct sphin_volume* volume, 404 struct sphin_refractive_index** refr_ind) 405 { 406 if (NULL == volume 407 || NULL == refr_ind) { 408 return RES_BAD_ARG; 409 } 410 *refr_ind = volume->refractive_index; 411 return RES_OK; 412 }