commit ed8d57093903a9bfa96aafed621b934631805589
parent a2dd33d043baa7591801c843c5206d7c137578f4
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Thu, 12 Feb 2026 11:54:58 +0100
Update the profile of the tree deserialization function
Group the input arguments into a structure and let the caller directly
provide the name of the file to be read. The caller can still directly
provide the stream if it is available. However, this update simplifies
the way the function can be called, as the caller no longer has to
manage the opening and closing of the source file.
Diffstat:
3 files changed, 125 insertions(+), 22 deletions(-)
diff --git a/src/sln.h b/src/sln.h
@@ -122,6 +122,21 @@ struct sln_tree_create_args {
static const struct sln_tree_create_args SLN_TREE_CREATE_ARGS_DEFAULT =
SLN_TREE_CREATE_ARGS_DEFAULT__;
+struct sln_tree_read_args {
+ /* Handle of the Star-HITRAN library to be used for loading isotopic metadata
+ * and line lists */
+ struct shtr* shtr;
+
+ /* Name of the file to read or of the provided stream.
+ * NULL <=> uses a default name for the stream to be read, which must
+ * therefore be defined. */
+ const char* filename; /* Name of the file to read */
+ FILE* file; /* Stream from where data are read. NULL <=> read from file */
+};
+#define SLN_TREE_READ_ARGS_NULL__ {NULL,NULL,NULL}
+static const struct sln_tree_read_args SLN_TREE_READ_ARGS_NULL =
+ SLN_TREE_READ_ARGS_NULL__;
+
struct sln_tree_desc {
size_t max_nlines_per_leaf;
double mesh_decimation_err;
@@ -227,12 +242,11 @@ sln_tree_create
const struct sln_tree_create_args* args,
struct sln_tree** tree);
-/* Load a tree serialized with the "sln_tree_write" function */
+/* Read a tree serialized with the "sln_tree_write" function */
SLN_API res_T
-sln_tree_create_from_stream
+sln_tree_read
(struct sln_device* sln,
- struct shtr* shtr,
- FILE* stream,
+ const struct sln_tree_read_args* args,
struct sln_tree** tree);
SLN_API res_T
diff --git a/src/sln_tree.c b/src/sln_tree.c
@@ -27,6 +27,13 @@
#include <rsys/cstr.h>
#include <rsys/math.h>
+struct stream {
+ const char* name;
+ FILE* fp;
+ int intern_fp; /* Define if the stream was internally opened */
+};
+static const struct stream STREAM_NULL = {NULL, NULL, 0};
+
/*******************************************************************************
* Helper functions
******************************************************************************/
@@ -223,6 +230,76 @@ check_sln_tree_create_args
}
static res_T
+check_sln_tree_read_args
+ (struct sln_device* sln,
+ const char* caller,
+ const struct sln_tree_read_args* args)
+{
+ if(!args) return RES_BAD_ARG;
+
+ if(!args->shtr) {
+ ERROR(sln,
+ "%s: the handle to the Star-HITRAN library is missing.\n", caller);
+ return RES_BAD_ARG;
+ }
+
+ if(!args->file && !args->filename) {
+ ERROR(sln,
+ "%s: the source file is missing. No file name or stream is provided.\n",
+ caller);
+ return RES_BAD_ARG;
+ }
+
+ return RES_OK;
+}
+
+static INLINE void
+stream_release(struct stream* stream)
+{
+ ASSERT(stream);
+ if(stream->intern_fp && stream->fp) CHK(fclose(stream->fp) == 0);
+}
+
+static res_T
+stream_init
+ (struct sln_device* sln,
+ const char* caller,
+ const char* name, /* NULL <=> default stream name */
+ FILE* fp, /* NULL <=> open file "name" */
+ const char* mode, /* mode in fopen */
+ struct stream* stream)
+{
+ res_T res = RES_OK;
+
+ ASSERT(sln && caller && stream);
+ ASSERT(fp || (name && mode));
+
+ *stream = STREAM_NULL;
+
+ if(fp) {
+ stream->intern_fp = 0;
+ stream->name = name ? name : "stream";
+ stream->fp = fp;
+
+ } else {
+ stream->intern_fp = 1;
+ stream->name = name;
+ if(!(stream->fp = fopen(name, mode))) {
+ ERROR(sln, "%s:%s: error opening file -- %s\n",
+ caller, name, strerror(errno));
+ res = RES_IO_ERR;
+ goto error;
+ }
+ }
+
+exit:
+ return res;
+error:
+ if(stream->intern_fp && stream->fp) CHK(fclose(stream->fp) == 0);
+ goto exit;
+}
+
+static res_T
create_tree
(struct sln_device* sln,
const char* caller,
@@ -312,31 +389,33 @@ error:
}
res_T
-sln_tree_create_from_stream
+sln_tree_read
(struct sln_device* sln,
- struct shtr* shtr,
- FILE* stream,
+ const struct sln_tree_read_args* args,
struct sln_tree** out_tree)
{
struct shtr_line_list_read_args rlines_args = SHTR_LINE_LIST_READ_ARGS_NULL;
+ struct stream stream = STREAM_NULL;
struct sln_tree* tree = NULL;
size_t n = 0;
int version = 0;
res_T res = RES_OK;
- if(!sln || !shtr || !stream || !out_tree) {
- res = RES_BAD_ARG;
- goto error;
- }
+ if(!sln || !out_tree) { res = RES_BAD_ARG; goto error; }
+ res = check_sln_tree_read_args(sln, FUNC_NAME, args);
+ if(res != RES_OK) goto error;
res = create_tree(sln, FUNC_NAME, &tree);
if(res != RES_OK) goto error;
+ res = stream_init(sln, FUNC_NAME, args->filename, args->file, "r", &stream);
+ if(res != RES_OK) goto error;
+
#define READ(Var, Nb) { \
- if(fread((Var), sizeof(*(Var)), (Nb), stream) != (Nb)) { \
- if(feof(stream)) { \
+ if(fread((Var), sizeof(*(Var)), (Nb), stream.fp) != (Nb)) { \
+ if(feof(stream.fp)) { \
res = RES_BAD_ARG; \
- } else if(ferror(stream)) { \
+ } else if(ferror(stream.fp)) { \
res = RES_IO_ERR; \
} else { \
res = RES_UNKNOWN_ERR; \
@@ -370,14 +449,16 @@ sln_tree_create_from_stream
READ(&tree->args.mesh_type, 1);
#undef READ
- res = shtr_isotope_metadata_create_from_stream(shtr, stream, &tree->args.metadata);
+ res = shtr_isotope_metadata_create_from_stream
+ (args->shtr, stream.fp, &tree->args.metadata);
if(res != RES_OK) goto error;
- rlines_args.file = stream;
- res = shtr_line_list_read(shtr, &rlines_args, &tree->args.lines);
+ rlines_args.file = stream.fp;
+ res = shtr_line_list_read(args->shtr, &rlines_args, &tree->args.lines);
if(res != RES_OK) goto error;
exit:
+ stream_release(&stream);
if(out_tree) *out_tree = tree;
return res;
error:
diff --git a/src/test_sln_tree.c b/src/test_sln_tree.c
@@ -314,6 +314,7 @@ test_tree_serialization
const struct sln_tree_create_args* tree_args,
struct shtr* shtr)
{
+ struct sln_tree_read_args args = SLN_TREE_READ_ARGS_NULL;
struct sln_tree* tree1 = NULL;
struct sln_tree* tree2 = NULL;
FILE* fp = NULL;
@@ -326,11 +327,18 @@ test_tree_serialization
CHK(sln_tree_write(tree1, fp) == RES_OK);
rewind(fp);
- CHK(sln_tree_create_from_stream(NULL, shtr, fp, &tree2) == RES_BAD_ARG);
- CHK(sln_tree_create_from_stream(sln, NULL, fp, &tree2) == RES_BAD_ARG);
- CHK(sln_tree_create_from_stream(sln, shtr, NULL, &tree2) == RES_BAD_ARG);
- CHK(sln_tree_create_from_stream(sln, shtr, fp, NULL) == RES_BAD_ARG);
- CHK(sln_tree_create_from_stream(sln, shtr, fp, &tree2) == RES_OK);
+ args.shtr = shtr;
+ args.file = fp;
+ CHK(sln_tree_read(NULL, &args, &tree2) == RES_BAD_ARG);
+ CHK(sln_tree_read(sln, NULL, &tree2) == RES_BAD_ARG);
+ args.shtr = NULL;
+ CHK(sln_tree_read(sln, &args, &tree2) == RES_BAD_ARG);
+ args.shtr = shtr;
+ args.file = NULL;
+ CHK(sln_tree_read(sln, &args, &tree2) == RES_BAD_ARG);
+ args.file = fp;
+ CHK(sln_tree_read(sln, &args, NULL) == RES_BAD_ARG);
+ CHK(sln_tree_read(sln, &args, &tree2) == RES_OK);
fclose(fp);
check_tree_equality(tree1, tree2);