rngrd

Describe a surface and its physical properties
git clone git://git.meso-star.fr/rngrd.git
Log | Files | Refs | README | LICENSE

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:
Msrc/rngrd.c | 15+++++++++++++++
Msrc/rngrd.h | 8++++++++
Msrc/rngrd_c.h | 4++++
Rsrc/rngrd_setup_mesh.c -> src/rngrd_mesh.c | 0
Asrc/rngrd_properties.c | 281+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/rngrd_setup_properties.c | 239-------------------------------------------------------------------------------
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; -}