commit da90d23aa3ff52a6734cf38880ef5231f9d13085
parent 86c79f446dae8b2fee6ca5de99d0c625be33be2c
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Fri, 15 Jul 2022 11:28:46 +0200
Add the rngrd_validate function
Diffstat:
6 files changed, 308 insertions(+), 239 deletions(-)
diff --git a/src/rngrd.c b/src/rngrd.c
@@ -177,3 +177,18 @@ rngrd_ref_put(struct rngrd* ground)
ref_put(&ground->ref, release_rngrd);
return RES_OK;
}
+
+res_T
+rngrd_validate(const struct rngrd* ground)
+{
+ res_T res = RES_OK;
+ if(!ground) return RES_BAD_ARG;
+
+ res = check_properties(ground);
+ if(res != RES_OK) goto error;
+
+exit:
+ return res;
+error:
+ goto exit;
+}
diff --git a/src/rngrd.h b/src/rngrd.h
@@ -115,4 +115,12 @@ RNGRD_API res_T
rngrd_ref_put
(struct rngrd* ground);
+/* Validates ground data. Data checks have already been done on load, but this
+ * function performs longer tests: for example, it iterates over all surface
+ * properties to check their validity against the mesh they are associated with
+ * and the material list loaded */
+RNGRD_API res_T
+rngrd_validate
+ (const struct rngrd* ground);
+
#endif /* RNGRD_H */
diff --git a/src/rngrd_c.h b/src/rngrd_c.h
@@ -74,4 +74,8 @@ setup_properties
(struct rngrd* ground,
const struct rngrd_create_args* args);
+extern LOCAL_SYM res_T
+check_properties
+ (const struct rngrd* ground);
+
#endif /* RNGRD_C_H */
diff --git a/src/rngrd_setup_mesh.c b/src/rngrd_mesh.c
diff --git a/src/rngrd_properties.c b/src/rngrd_properties.c
@@ -0,0 +1,281 @@
+/* Copyright (C) 2022 Centre National de la Recherche Scientifique
+ * Copyright (C) 2022 Institut de Physique du Globe de Paris
+ * Copyright (C) 2022 |Méso|Star> (contact@meso-star.com)
+ * Copyright (C) 2022 Université de Reims Champagne-Ardenne
+ * Copyright (C) 2022 Université de Versaille Saint-Quentin
+ * Copyright (C) 2022 Université Paul Sabatier (contact@laplace.univ-tlse.fr)
+ *
+ * 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 /* strtok_r and wordexp */
+
+#include "rngrd.h"
+#include "rngrd_c.h"
+#include "rngrd_log.h"
+
+#include <star/sbuf.h>
+
+#include <rsys/cstr.h>
+#include <rsys/text_reader.h>
+
+#include <string.h>
+#include <wordexp.h>
+
+/*******************************************************************************
+ * Helper functions
+ ******************************************************************************/
+static res_T
+check_sbuf_desc
+ (const struct rngrd* ground,
+ const struct sbuf_desc* desc,
+ const struct rngrd_create_args* args)
+{
+ ASSERT(ground && desc && args);
+
+ if(desc->size != ground->ntriangles) {
+ log_err(ground,
+ "%s: no sufficient surface properties regarding the mesh %s.\n",
+ args->props_filename, args->smsh_filename);
+ return RES_BAD_ARG;
+ }
+
+ if(desc->szitem != 8
+ || desc->alitem != 8
+ || desc->pitch != 8) {
+ log_err(ground, "%s: unexpected layout of properties\n",
+ args->props_filename);
+ return RES_BAD_ARG;
+ }
+
+ return RES_OK;
+}
+
+static res_T
+parse_mtl(struct rngrd* ground, struct txtrdr* txtrdr, struct mrumtl** out_mtl)
+{
+ wordexp_t wexp;
+ char* tk = NULL;
+ char* tk_ctx = NULL;
+ struct mrumtl_create_args args = MRUMTL_CREATE_ARGS_DEFAULT;
+ struct mrumtl* mtl = NULL;
+ int wexp_is_allocated = 1;
+ res_T res = RES_OK;
+ int err = 0;
+ ASSERT(ground && txtrdr && out_mtl);
+
+ res = txtrdr_read_line(txtrdr);
+ if(res != RES_OK) {
+ log_err(ground, "%s: can't read the line `%lu' -- %s\n",
+ txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr),
+ res_to_cstr(res));
+ goto error;
+ }
+
+ if(!txtrdr_get_cline(txtrdr)) {
+ const size_t nexpect = darray_mtl_size_get(&ground->mtls);
+ const size_t nparsed = (size_t)(out_mtl - darray_mtl_cdata_get(&ground->mtls));
+ log_err(ground,
+ "%s:%lu: missing a material filename. "
+ "Expecting %lu material%s while %lu %s parsed.\n",
+ txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr),
+ (unsigned long)nexpect, nexpect == 1 ? " " : "s ",
+ (unsigned long)nparsed, nparsed > 1 ? "were" : "was");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ tk = strtok_r(txtrdr_get_line(txtrdr), "", &tk_ctx);
+ ASSERT(tk);
+
+ err = wordexp(tk, &wexp, 0/*flags*/);
+ if(err) {
+ log_err(ground, "%s:%lu: unable to expand material filename\n",
+ txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr));
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ wexp_is_allocated = 1;
+ ASSERT(wexp.we_wordc != 0);
+
+ args.verbose = ground->verbose;
+ res = mrumtl_create(&args, &mtl);
+ if(res != RES_OK) {
+ log_err(ground, "%s:%lu: could not create the MruMtl data structure\n",
+ txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr));
+ goto error;
+ }
+
+ res = mrumtl_load(mtl, wexp.we_wordv[0]);
+ if(res != RES_OK) goto error;
+
+ if(wexp.we_wordc > 1) {
+ log_warn(ground, "%s:%lu: unexpected text `%s'\n",
+ txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr),
+ wexp.we_wordv[1]);
+ }
+
+exit:
+ if(wexp_is_allocated) wordfree(&wexp);
+ *out_mtl = mtl;
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+parse_mtllst(struct rngrd* ground, const struct rngrd_create_args* args)
+{
+ struct txtrdr* txtrdr = NULL;
+ char* tk = NULL;
+ char* tk_ctx = NULL;
+ size_t imtl = 0;
+ unsigned long nmtls = 0;
+ res_T res = RES_OK;
+ ASSERT(ground && args);
+
+ res = txtrdr_file(ground->allocator, args->mtllst_filename, '#', &txtrdr);
+ if(res != RES_OK) {
+ log_err(ground, "Could not create text reader to parse file `%s' -- %s\n",
+ args->mtllst_filename, res_to_cstr(res));
+ goto error;
+ }
+
+ res = txtrdr_read_line(txtrdr);
+ if(res != RES_OK) {
+ log_err(ground, "%s: can't read the line %lu --%s\n",
+ txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr),
+ res_to_cstr(res));
+ goto error;
+ }
+
+ if(!txtrdr_get_cline(txtrdr)) {
+ log_err(ground, "%s: file cannot be empty\n", txtrdr_get_name(txtrdr));
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ tk = strtok_r(txtrdr_get_line(txtrdr), " \t", &tk_ctx);
+ ASSERT(tk);
+
+ res = cstr_to_ulong(tk, &nmtls);
+ if(res == RES_OK && nmtls == 0) res = RES_BAD_ARG;
+ if(res != RES_OK) {
+ log_err(ground, "%s:%lu: invalid number of materials %lu\n",
+ txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr),
+ nmtls);
+ goto error;
+ }
+
+ res = darray_mtl_resize(&ground->mtls, nmtls);
+ if(res != RES_OK) {
+ log_err(ground, "%s: could not allocate the list of %lu materials -- %s\n",
+ txtrdr_get_name(txtrdr), nmtls, res_to_cstr(res));
+ goto error;
+ }
+
+ tk = strtok_r(NULL, " \t", &tk_ctx);
+ if(tk) {
+ log_warn(ground, "%s:%lu: unexpected text `%s'\n",
+ txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr), tk);
+ }
+
+ FOR_EACH(imtl, 0, nmtls) {
+ struct mrumtl** mtl = darray_mtl_data_get(&ground->mtls)+imtl;
+ res = parse_mtl(ground, txtrdr, mtl);
+ if(res != RES_OK) goto error;
+ }
+
+exit:
+ if(txtrdr) txtrdr_ref_put(txtrdr);
+ return res;
+error:
+ goto exit;
+}
+
+/*******************************************************************************
+ * Local function
+ ******************************************************************************/
+res_T
+setup_properties(struct rngrd* ground, const struct rngrd_create_args* args)
+{
+ struct sbuf_create_args sbuf_args = SBUF_CREATE_ARGS_DEFAULT;
+ struct sbuf_desc sbuf_desc = SBUF_DESC_NULL;
+ res_T res = RES_OK;
+ ASSERT(ground && args);
+
+ res = parse_mtllst(ground, args);
+ if(res != RES_OK) goto error;
+
+ /* Create the Star-Buffer loader */
+ sbuf_args.logger = ground->logger;
+ sbuf_args.allocator = ground->allocator;
+ sbuf_args.verbose = ground->verbose;
+ res = sbuf_create(&sbuf_args, &ground->props);
+ if(res != RES_OK) goto error;
+
+ /* Load and retrieve properties */
+ res = sbuf_load(ground->props, args->props_filename);
+ if(res != RES_OK) goto error;
+ res = sbuf_get_desc(ground->props, &sbuf_desc);
+ if(res != RES_OK) goto error;
+ res = check_sbuf_desc(ground, &sbuf_desc, args);
+ if(res != RES_OK) goto error;
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+res_T
+check_properties(const struct rngrd* ground)
+{
+ struct sbuf_desc sbuf_desc = SBUF_DESC_NULL;
+ size_t i;
+ res_T res = RES_OK;
+ ASSERT(ground);
+
+ /* The descriptor layout was already check during rngrd creation */
+ res = sbuf_get_desc(ground->props, &sbuf_desc);
+ if(res != RES_OK) goto error;
+
+ FOR_EACH(i, 0, sbuf_desc.size) {
+ const struct ALIGN(8) { uint32_t mtl_id; float temperature; }* item = NULL;
+ item = sbuf_desc_at(&sbuf_desc, i);
+
+ ASSERT(IS_ALIGNED(item, sbuf_desc.alitem));
+ ASSERT(sizeof(*item) == sbuf_desc.szitem);
+
+ if(item->mtl_id >= darray_mtl_size_get(&ground->mtls)) {
+ log_err(ground,
+ "%s: triangle %lu: invalid material id `%u'. It must be in [0, %lu]\n",
+ str_cget(&ground->name), i, item->mtl_id,
+ darray_mtl_size_get(&ground->mtls));
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ if(item->temperature < 0) {
+ log_err(ground, "%s: triangle %lu: invalid temperature `%g'\n",
+ str_cget(&ground->name), i, item->temperature);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ }
+
+exit:
+ return res;
+error:
+ goto exit;
+}
diff --git a/src/rngrd_setup_properties.c b/src/rngrd_setup_properties.c
@@ -1,239 +0,0 @@
-/* Copyright (C) 2022 Centre National de la Recherche Scientifique
- * Copyright (C) 2022 Institut de Physique du Globe de Paris
- * Copyright (C) 2022 |Méso|Star> (contact@meso-star.com)
- * Copyright (C) 2022 Université de Reims Champagne-Ardenne
- * Copyright (C) 2022 Université de Versaille Saint-Quentin
- * Copyright (C) 2022 Université Paul Sabatier (contact@laplace.univ-tlse.fr)
- *
- * 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 /* strtok_r and wordexp */
-
-#include "rngrd.h"
-#include "rngrd_c.h"
-#include "rngrd_log.h"
-
-#include <star/sbuf.h>
-
-#include <rsys/cstr.h>
-#include <rsys/text_reader.h>
-
-#include <string.h>
-#include <wordexp.h>
-
-/*******************************************************************************
- * Helper functions
- ******************************************************************************/
-static res_T
-check_sbuf_desc
- (const struct rngrd* ground,
- const struct sbuf_desc* desc,
- const struct rngrd_create_args* args)
-{
- ASSERT(ground && desc && args);
-
- if(desc->size != ground->ntriangles) {
- log_err(ground,
- "%s: no sufficient surface properties regarding the mesh %s.\n",
- args->props_filename, args->smsh_filename);
- return RES_BAD_ARG;
- }
-
- if(desc->szitem != 8
- || desc->alitem != 8
- || desc->pitch != 8) {
- log_err(ground, "%s: unexpected layout of properties\n",
- args->props_filename);
- return RES_BAD_ARG;
- }
-
- return RES_OK;
-}
-
-static res_T
-parse_mtl(struct rngrd* ground, struct txtrdr* txtrdr, struct mrumtl** out_mtl)
-{
- wordexp_t wexp;
- char* tk = NULL;
- char* tk_ctx = NULL;
- struct mrumtl_create_args args = MRUMTL_CREATE_ARGS_DEFAULT;
- struct mrumtl* mtl = NULL;
- int wexp_is_allocated = 1;
- res_T res = RES_OK;
- int err = 0;
- ASSERT(ground && txtrdr && out_mtl);
-
- res = txtrdr_read_line(txtrdr);
- if(res != RES_OK) {
- log_err(ground, "%s: can't read the line `%lu' -- %s\n",
- txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr),
- res_to_cstr(res));
- goto error;
- }
-
- if(!txtrdr_get_cline(txtrdr)) {
- const size_t nexpect = darray_mtl_size_get(&ground->mtls);
- const size_t nparsed = (size_t)(out_mtl - darray_mtl_cdata_get(&ground->mtls));
- log_err(ground,
- "%s:%lu: missing a material filename. "
- "Expecting %lu material%s while %lu %s parsed.\n",
- txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr),
- (unsigned long)nexpect, nexpect == 1 ? " " : "s ",
- (unsigned long)nparsed, nparsed > 1 ? "were" : "was");
- res = RES_BAD_ARG;
- goto error;
- }
-
- tk = strtok_r(txtrdr_get_line(txtrdr), "", &tk_ctx);
- ASSERT(tk);
-
- err = wordexp(tk, &wexp, 0/*flags*/);
- if(err) {
- log_err(ground, "%s:%lu: unable to expand material filename\n",
- txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr));
- res = RES_BAD_ARG;
- goto error;
- }
- wexp_is_allocated = 1;
- ASSERT(wexp.we_wordc != 0);
-
- args.verbose = ground->verbose;
- res = mrumtl_create(&args, &mtl);
- if(res != RES_OK) {
- log_err(ground, "%s:%lu: could not create the MruMtl data structure\n",
- txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr));
- goto error;
- }
-
- res = mrumtl_load(mtl, wexp.we_wordv[0]);
- if(res != RES_OK) goto error;
-
- if(wexp.we_wordc > 1) {
- log_warn(ground, "%s:%lu: unexpected text `%s'\n",
- txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr),
- wexp.we_wordv[1]);
- }
-
-exit:
- if(wexp_is_allocated) wordfree(&wexp);
- *out_mtl = mtl;
- return res;
-error:
- goto exit;
-}
-
-static res_T
-parse_mtllst(struct rngrd* ground, const struct rngrd_create_args* args)
-{
- struct txtrdr* txtrdr = NULL;
- char* tk = NULL;
- char* tk_ctx = NULL;
- size_t imtl = 0;
- unsigned long nmtls = 0;
- res_T res = RES_OK;
- ASSERT(ground && args);
-
- res = txtrdr_file(ground->allocator, args->mtllst_filename, '#', &txtrdr);
- if(res != RES_OK) {
- log_err(ground, "Could not create text reader to parse file `%s' -- %s\n",
- args->mtllst_filename, res_to_cstr(res));
- goto error;
- }
-
- res = txtrdr_read_line(txtrdr);
- if(res != RES_OK) {
- log_err(ground, "%s: can't read the line %lu --%s\n",
- txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr),
- res_to_cstr(res));
- goto error;
- }
-
- if(!txtrdr_get_cline(txtrdr)) {
- log_err(ground, "%s: file cannot be empty\n", txtrdr_get_name(txtrdr));
- res = RES_BAD_ARG;
- goto error;
- }
-
- tk = strtok_r(txtrdr_get_line(txtrdr), " \t", &tk_ctx);
- ASSERT(tk);
-
- res = cstr_to_ulong(tk, &nmtls);
- if(res == RES_OK && nmtls == 0) res = RES_BAD_ARG;
- if(res != RES_OK) {
- log_err(ground, "%s:%lu: invalid number of materials %lu\n",
- txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr),
- nmtls);
- goto error;
- }
-
- res = darray_mtl_resize(&ground->mtls, nmtls);
- if(res != RES_OK) {
- log_err(ground, "%s: could not allocate the list of %lu materials -- %s\n",
- txtrdr_get_name(txtrdr), nmtls, res_to_cstr(res));
- goto error;
- }
-
- tk = strtok_r(NULL, " \t", &tk_ctx);
- if(tk) {
- log_warn(ground, "%s:%lu: unexpected text `%s'\n",
- txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr), tk);
- }
-
- FOR_EACH(imtl, 0, nmtls) {
- struct mrumtl** mtl = darray_mtl_data_get(&ground->mtls)+imtl;
- res = parse_mtl(ground, txtrdr, mtl);
- if(res != RES_OK) goto error;
- }
-
-exit:
- if(txtrdr) txtrdr_ref_put(txtrdr);
- return res;
-error:
- goto exit;
-}
-
-/*******************************************************************************
- * Local function
- ******************************************************************************/
-res_T
-setup_properties(struct rngrd* ground, const struct rngrd_create_args* args)
-{
- struct sbuf_create_args sbuf_args = SBUF_CREATE_ARGS_DEFAULT;
- struct sbuf_desc sbuf_desc = SBUF_DESC_NULL;
- res_T res = RES_OK;
- ASSERT(ground && args);
-
- res = parse_mtllst(ground, args);
- if(res != RES_OK) goto error;
-
- /* Create the Star-Buffer loader */
- sbuf_args.logger = ground->logger;
- sbuf_args.allocator = ground->allocator;
- sbuf_args.verbose = ground->verbose;
- res = sbuf_create(&sbuf_args, &ground->props);
- if(res != RES_OK) goto error;
-
- /* Load and retrieve properties */
- res = sbuf_load(ground->props, args->props_filename);
- if(res != RES_OK) goto error;
- res = sbuf_get_desc(ground->props, &sbuf_desc);
- if(res != RES_OK) goto error;
- res = check_sbuf_desc(ground, &sbuf_desc, args);
- if(res != RES_OK) goto error;
-
-exit:
- return res;
-error:
- goto exit;
-}