star-hitran

Load line-by-line data from the HITRAN database
git clone git://git.meso-star.fr/star-hitran.git
Log | Files | Refs | README | LICENSE

commit 62e8c3110adf6391dc19afc8882dcd5264afdbc9
parent 8f602bfb1a7820e76b38ff9d618556b3425a9586
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Mon,  5 Jan 2026 18:14:41 +0100

Update to the line list loading API

The input arguments are grouped together in a structure in order to
anticipate the addition of new arguments (compression level, disk
storage file, etc.), whose default behavior defined by
SHTR_LINE_LIST_LOAD_ARGS_NULL ensures the consistency of the API (but
not the ABI). Callers can therefore be sure that future updates will not
impact their code, which will nevertheless need to be recompiled.

This change is accompanied by the removal of the
shtr_line_list_load_stream function, which is actually merged with the
shtr_line_list_load function. Depending on the value of the input
arguments, in particular the "file" member variable of the new input
structure, the line parameters are loaded either from a stream or from a
file on disk.

The tests and the shtr utility have been updated to support these API
changes.

Diffstat:
Msrc/shtr.h | 19++++++++++---------
Msrc/shtr_line_list.c | 54++++++++++++++++++++++++++++++------------------------
Msrc/shtr_main.c | 9++++++---
Msrc/test_shtr_lines.c | 60++++++++++++++++++++++++++++++++++--------------------------
4 files changed, 80 insertions(+), 62 deletions(-)

diff --git a/src/shtr.h b/src/shtr.h @@ -153,10 +153,18 @@ struct shtr_create_args { struct mem_allocator* allocator; /* NULL <=> use default allocator */ int verbose; /* Verbosity level */ }; -#define SHTR_CREATE_ARGS_DEFAULT__ {0} +#define SHTR_CREATE_ARGS_DEFAULT__ {NULL, NULL, 0} static const struct shtr_create_args SHTR_CREATE_ARGS_DEFAULT = SHTR_CREATE_ARGS_DEFAULT__; +struct shtr_line_list_load_args { + const char* filename; /* Name of the file to load or of the provided stream */ + FILE* file; /* Stream from where data are loaded. NULL <=> load from file */ +}; +#define SHTR_LINE_LIST_LOAD_ARGS_NULL__ {NULL, NULL} +static const struct shtr_line_list_load_args SHTR_LINE_LIST_LOAD_ARGS_NULL = + SHTR_LINE_LIST_LOAD_ARGS_NULL__; + BEGIN_DECLS /******************************************************************************* @@ -241,14 +249,7 @@ shtr_isotope_metadata_write SHTR_API res_T shtr_line_list_load (struct shtr* shtr, - const char* path, - struct shtr_line_list** list); - -SHTR_API res_T -shtr_line_list_load_stream - (struct shtr* shtr, - FILE* stream, - const char* stream_name, /* NULL <=> use default stream name */ + const struct shtr_line_list_load_args* args, struct shtr_line_list** list); /* Load the line list serialized with the "shtr_line_list_write" function */ diff --git a/src/shtr_line_list.c b/src/shtr_line_list.c @@ -28,6 +28,17 @@ * Helper functions ******************************************************************************/ static res_T +check_shtr_line_list_load_args(const struct shtr_line_list_load_args* args) +{ + if(!args) return RES_BAD_ARG; + + /* Source is missing */ + if(!args->file && !args->filename) return RES_BAD_ARG; + + return RES_OK; +} + +static res_T create_line_list(struct shtr* shtr, struct shtr_line_list** out_list) { struct shtr_line_list* list = NULL; @@ -363,47 +374,42 @@ release_lines(ref_T * ref) res_T shtr_line_list_load (struct shtr* shtr, - const char* path, + const struct shtr_line_list_load_args* args, struct shtr_line_list** list) { FILE* file = NULL; + const char* name = NULL; res_T res = RES_OK; - if(!shtr || !path || !list) { - res = RES_BAD_ARG; - goto error; - } + if(!shtr || !list) { res = RES_BAD_ARG; goto error; } + res = check_shtr_line_list_load_args(args); + if(res != RES_OK) goto error; - file = fopen(path, "r"); - if(!file) { - ERROR(shtr, "%s: error opening file `%s'.\n", FUNC_NAME, path); - res = RES_IO_ERR; - goto error; + if(args->file) { /* Load from stream */ + name = args->filename ? args->filename : "<stream>"; + file = args->file; + + } else { /* Load from file */ + name = args->filename; + file = fopen(args->filename, "r"); + if(!file) { + ERROR(shtr, "%s: error opening file `%s'.\n", FUNC_NAME, args->filename); + res = RES_IO_ERR; + goto error; + } } - res = load_stream(shtr, file, path, list); + res = load_stream(shtr, file, name, list); if(res != RES_OK) goto error; exit: - if(file) fclose(file); + if(file && file != args->file) fclose(file); return res; error: goto exit; } res_T -shtr_line_list_load_stream - (struct shtr* shtr, - FILE* stream, - const char* stream_name, - struct shtr_line_list** list) -{ - if(!shtr || !stream || !list) return RES_BAD_ARG; - return load_stream - (shtr, stream, stream_name ? stream_name : "<stream>", list); -} - -res_T shtr_line_list_create_from_stream (struct shtr* shtr, FILE* stream, diff --git a/src/shtr_main.c b/src/shtr_main.c @@ -135,12 +135,15 @@ load_molparam(const struct cmd* cmd, struct shtr_isotope_metadata** molparam) static res_T load_lines(const struct cmd* cmd, struct shtr_line_list** lines) { + struct shtr_line_list_load_args args = SHTR_LINE_LIST_LOAD_ARGS_NULL__; ASSERT(cmd && lines && cmd->args.lines); - if(!strcmp(cmd->args.lines, STDIN_NAME)) { - return shtr_line_list_load_stream(cmd->shtr, stdin, "stdin", lines); + if(strcmp(cmd->args.lines, STDIN_NAME)) { + args.filename = cmd->args.lines; } else { - return shtr_line_list_load(cmd->shtr, cmd->args.lines, lines); + args.file = stdin; + args.filename = "stdin"; } + return shtr_line_list_load(cmd->shtr, &args, lines); } static void diff --git a/src/test_shtr_lines.c b/src/test_shtr_lines.c @@ -138,6 +138,7 @@ test_load(struct shtr* shtr) struct shtr_line_list_info info = SHTR_LINE_LIST_INFO_NULL; struct shtr_line_list_info info_ref = SHTR_LINE_LIST_INFO_NULL; struct shtr_line line = SHTR_LINE_NULL; + struct shtr_line_list_load_args args = SHTR_LINE_LIST_LOAD_ARGS_NULL__; const char* filename = "test_lines.txt"; FILE* fp = NULL; size_t i, n; @@ -146,10 +147,11 @@ test_load(struct shtr* shtr) print_lines(fp, l, nlines); rewind(fp); - CHK(shtr_line_list_load_stream(NULL, fp, NULL, &list) == RES_BAD_ARG); - CHK(shtr_line_list_load_stream(shtr, NULL, NULL, &list) == RES_BAD_ARG); - CHK(shtr_line_list_load_stream(shtr, fp, NULL, NULL) == RES_BAD_ARG); - CHK(shtr_line_list_load_stream(shtr, fp, NULL, &list) == RES_OK); + args.file = fp; + CHK(shtr_line_list_load(NULL, &args, &list) == RES_BAD_ARG); + CHK(shtr_line_list_load(shtr, NULL, &list) == RES_BAD_ARG); + CHK(shtr_line_list_load(shtr, &args, NULL) == RES_BAD_ARG); + CHK(shtr_line_list_load(shtr, &args, &list) == RES_OK); CHK(shtr_line_list_get_info(NULL, &info) == RES_BAD_ARG); CHK(shtr_line_list_get_info(list, NULL) == RES_BAD_ARG); @@ -205,10 +207,12 @@ test_load(struct shtr* shtr) CHK(fclose(fp) == 0); - CHK(shtr_line_list_load(NULL, filename, &list) == RES_BAD_ARG); + args.file = NULL; + args.filename = filename; + CHK(shtr_line_list_load(NULL, &args, &list) == RES_BAD_ARG); CHK(shtr_line_list_load(shtr, NULL, &list) == RES_BAD_ARG); - CHK(shtr_line_list_load(shtr, filename, NULL) == RES_BAD_ARG); - CHK(shtr_line_list_load(shtr, filename, &list) == RES_OK); + CHK(shtr_line_list_load(shtr, &args, NULL) == RES_BAD_ARG); + CHK(shtr_line_list_load(shtr, &args, &list) == RES_OK); CHK(shtr_line_list_get_info(list, &info) == RES_OK); @@ -228,13 +232,13 @@ test_line (struct shtr* shtr, const struct shtr_line* ln, const res_T res) { struct shtr_line_list* list = NULL; - FILE* fp = NULL; + struct shtr_line_list_load_args args = SHTR_LINE_LIST_LOAD_ARGS_NULL__; - CHK(fp = tmpfile()); - print_lines(fp, ln, 1); - rewind(fp); - CHK(shtr_line_list_load_stream(shtr, fp, NULL, &list) == res); - CHK(fclose(fp) == 0); + CHK(args.file = tmpfile()); + print_lines(args.file, ln, 1); + rewind(args.file); + CHK(shtr_line_list_load(shtr, &args, &list) == res); + CHK(fclose(args.file) == 0); if(res == RES_OK) CHK(shtr_line_list_ref_put(list) == RES_OK); } @@ -247,7 +251,7 @@ test_load_failures(struct shtr* shtr) }; struct shtr_line ln; struct shtr_line_list* list = NULL; - FILE* fp = NULL; + struct shtr_line_list_load_args args = SHTR_LINE_LIST_LOAD_ARGS_NULL__; /* Check that the reference line is valid */ test_line(shtr, &ln_ref, RES_OK); @@ -287,14 +291,14 @@ test_load_failures(struct shtr* shtr) test_line(shtr, &ln, RES_BAD_ARG); /* Lines are not correctly sorted */ - CHK(fp = tmpfile()); + CHK(args.file = tmpfile()); ln = ln_ref; - print_lines(fp, &ln, 1); + print_lines(args.file, &ln, 1); ln.wavenumber -= 1e-4; - print_lines(fp, &ln, 1); - rewind(fp); - CHK(shtr_line_list_load_stream(shtr, fp, NULL, &list) == RES_BAD_ARG); - CHK(fclose(fp) == 0); + print_lines(args.file, &ln, 1); + rewind(args.file); + CHK(shtr_line_list_load(shtr, &args, &list) == RES_BAD_ARG); + CHK(fclose(args.file) == 0); } static void @@ -334,16 +338,18 @@ test_serialization(struct shtr* shtr) }; const size_t nlines = sizeof(l) / sizeof(struct shtr_line); + struct shtr_line_list_load_args args = SHTR_LINE_LIST_LOAD_ARGS_NULL__; struct shtr_line_list* list1 = NULL; struct shtr_line_list* list2 = NULL; + FILE* fp = NULL; - CHK(fp = tmpfile()); - print_lines(fp, l, nlines); - rewind(fp); + CHK(args.file = tmpfile()); + print_lines(args.file, l, nlines); + rewind(args.file); - CHK(shtr_line_list_load_stream(shtr, fp, NULL, &list1) == RES_OK); - fclose(fp); + CHK(shtr_line_list_load(shtr, &args, &list1) == RES_OK); + fclose(args.file); CHK(fp = tmpfile()); CHK(shtr_line_list_write(NULL, fp) == RES_BAD_ARG); @@ -387,11 +393,13 @@ check_line(const struct shtr_line* ln) static void test_load_file(struct shtr* shtr, const char* path) { + struct shtr_line_list_load_args args = SHTR_LINE_LIST_LOAD_ARGS_NULL__; struct shtr_line_list* list = NULL; size_t i, n; CHK(path); printf("Loading `%s'.\n", path); - CHK(shtr_line_list_load(shtr, path, &list) == RES_OK); + args.filename = path; + CHK(shtr_line_list_load(shtr, &args, &list) == RES_OK); CHK(shtr_line_list_get_size(list, &n) == RES_OK); printf(" #lines: %lu\n", n);