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 777e9a7f0a2e7957e827256a005c0a3a81124a8f
parent bb650a63604a61ec01c02dcc123f9492a56b6fda
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Mon,  7 Feb 2022 09:55:37 +0100

Change shitran prefix to sht

Diffstat:
Mcmake/CMakeLists.txt | 64++++++++++++++++++++++++++++++++--------------------------------
Dsrc/shitran.c | 101-------------------------------------------------------------------------------
Dsrc/shitran.h | 99-------------------------------------------------------------------------------
Dsrc/shitran_c.h | 35-----------------------------------
Dsrc/shitran_isotopologues.c | 426-------------------------------------------------------------------------------
Dsrc/shitran_log.c | 127-------------------------------------------------------------------------------
Dsrc/shitran_log.h | 73-------------------------------------------------------------------------
Asrc/sht.c | 101+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/sht.h | 99+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/sht_c.h | 35+++++++++++++++++++++++++++++++++++
Asrc/sht_isotopologues.c | 426+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/sht_log.c | 127+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/sht_log.h | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/test_shitran.c | 74--------------------------------------------------------------------------
Asrc/test_sht.c | 74++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
15 files changed, 967 insertions(+), 967 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -17,10 +17,10 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. cmake_minimum_required(VERSION 3.1) -project(shitran C) +project(sht C) enable_testing() -set(SHITRAN_SOURCE_DIR ${PROJECT_SOURCE_DIR}/../src) +set(SHT_SOURCE_DIR ${PROJECT_SOURCE_DIR}/../src) option(NO_TEST "Do not build tests" OFF) ################################################################################ @@ -43,41 +43,41 @@ set(VERSION_MINOR 0) set(VERSION_PATCH 0) set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) -set(SHITRAN_FILES_SRC - shitran.c - shitran_log.c - shitran_isotopologues.c) -set(SHITRAN_FILES_INC - shitran_c.h - shitran_log.h) -set(SHITRAN_FILES_INC_API - shitran.h) - -set(SHITRAN_FILES_DOC COPYING README.md) - -# Prepend each file in the `SHITRAN_FILES_<SRC|INC>' list by `SHITRAN_SOURCE_DIR' -rcmake_prepend_path(SHITRAN_FILES_SRC ${SHITRAN_SOURCE_DIR}) -rcmake_prepend_path(SHITRAN_FILES_INC ${SHITRAN_SOURCE_DIR}) -rcmake_prepend_path(SHITRAN_FILES_INC_API ${SHITRAN_SOURCE_DIR}) -rcmake_prepend_path(SHITRAN_FILES_DOC ${PROJECT_SOURCE_DIR}/../) - -add_library(shitran SHARED ${SHITRAN_FILES_SRC} ${SHITRAN_FILES_INC} ${SHITRAN_FILES_INC_API}) -target_link_libraries(shitran RSys) - -set_target_properties(shitran PROPERTIES - DEFINE_SYMBOL SHITRAN_SHARED_BUILD +set(SHT_FILES_SRC + sht.c + sht_log.c + sht_isotopologues.c) +set(SHT_FILES_INC + sht_c.h + sht_log.h) +set(SHT_FILES_INC_API + sht.h) + +set(SHT_FILES_DOC COPYING README.md) + +# Prepend each file in the `SHT_FILES_<SRC|INC>' list by `SHT_SOURCE_DIR' +rcmake_prepend_path(SHT_FILES_SRC ${SHT_SOURCE_DIR}) +rcmake_prepend_path(SHT_FILES_INC ${SHT_SOURCE_DIR}) +rcmake_prepend_path(SHT_FILES_INC_API ${SHT_SOURCE_DIR}) +rcmake_prepend_path(SHT_FILES_DOC ${PROJECT_SOURCE_DIR}/../) + +add_library(sht SHARED ${SHT_FILES_SRC} ${SHT_FILES_INC} ${SHT_FILES_INC_API}) +target_link_libraries(sht RSys) + +set_target_properties(sht PROPERTIES + DEFINE_SYMBOL SHT_SHARED_BUILD VERSION ${VERSION} SOVERSION ${VERSION_MAJOR}) -rcmake_setup_devel(shitran StarHITRAN ${VERSION} star/shitran_version.h) +rcmake_setup_devel(sht StarHITRAN ${VERSION} star/sht_version.h) ################################################################################ # Add tests ################################################################################ if(NOT NO_TEST) function(build_test _name) - add_executable(${_name} ${SHITRAN_SOURCE_DIR}/${_name}.c) - target_link_libraries(${_name} shitran RSys ${ARGN}) + add_executable(${_name} ${SHT_SOURCE_DIR}/${_name}.c) + target_link_libraries(${_name} sht RSys ${ARGN}) endfunction() function(new_test _name) @@ -85,17 +85,17 @@ if(NOT NO_TEST) add_test(${_name} ${_name}) endfunction() - new_test(test_shitran) + new_test(test_sht) endif() ################################################################################ # Define output & install directories ################################################################################ -install(TARGETS shitran +install(TARGETS sht ARCHIVE DESTINATION bin LIBRARY DESTINATION lib RUNTIME DESTINATION bin) -install(FILES ${SHITRAN_FILES_INC_API} DESTINATION include/star) -install(FILES ${SHITRAN_FILES_DOC} DESTINATION share/doc/star-hitran) +install(FILES ${SHT_FILES_INC_API} DESTINATION include/star) +install(FILES ${SHT_FILES_DOC} DESTINATION share/doc/star-hitran) diff --git a/src/shitran.c b/src/shitran.c @@ -1,101 +0,0 @@ -/* Copyright (C) 2022 CNRS - LMD - * Copyright (C) 2022 |Meso|Star> (contact@meso-star.com) - * Copyright (C) 2022 Université Paul Sabatier - IRIT - * Copyright (C) 2022 Université Paul Sabatier - Laplace - * - * 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/>. */ - -#include "shitran.h" -#include "shitran_c.h" -#include "shitran_log.h" - -/******************************************************************************* - * Helper functions - ******************************************************************************/ -static INLINE res_T -check_shitran_create_args(const struct shitran_create_args* args) -{ - return args ? RES_OK : RES_BAD_ARG; -} - -static void -release_shitran(ref_T* ref) -{ - struct shitran* shitran = CONTAINER_OF(ref, struct shitran, ref); - ASSERT(ref); - if(shitran->logger == &shitran->logger__) logger_release(&shitran->logger__); - MEM_RM(shitran->allocator, shitran); -} - -/******************************************************************************* - * Exported functions - ******************************************************************************/ -res_T -shitran_create - (const struct shitran_create_args* args, - struct shitran** out_shitran) -{ - struct mem_allocator* allocator = NULL; - struct shitran* shitran = NULL; - res_T res = RES_OK; - - if(!out_shitran) { res = RES_BAD_ARG; goto error; } - res = check_shitran_create_args(args); - if(res != RES_OK) goto error; - - allocator = args->allocator ? args->allocator : &mem_default_allocator; - shitran = MEM_CALLOC(allocator, 1, sizeof(*shitran)); - if(!shitran) { - #define ERR_STR "Could not allocate the Star-HITRAN data structure.\n" - if(args->logger) { - logger_print(args->logger, LOG_ERROR, ERR_STR); - } else { - fprintf(stderr, MSG_ERROR_PREFIX ERR_STR); - } - #undef ERR_STR - res = RES_MEM_ERR; - goto error; - } - ref_init(&shitran->ref); - shitran->allocator = allocator; - shitran->verbose = args->verbose; - if(args->logger) { - shitran->logger = args->logger; - } else { - setup_log_default(shitran); - } - -exit: - if(out_shitran) *out_shitran = shitran; - return res; -error: - if(shitran) { SHITRAN(ref_put(shitran)); shitran = NULL; } - goto exit; -} - -res_T -shitran_ref_get(struct shitran* shitran) -{ - if(!shitran) return RES_BAD_ARG; - ref_get(&shitran->ref); - return RES_OK; -} - -res_T -shitran_ref_put(struct shitran* shitran) -{ - if(!shitran) return RES_BAD_ARG; - ref_put(&shitran->ref, release_shitran); - return RES_OK; -} diff --git a/src/shitran.h b/src/shitran.h @@ -1,99 +0,0 @@ -/* Copyright (C) 2022 CNRS - LMD - * Copyright (C) 2022 |Meso|Star> (contact@meso-star.com) - * Copyright (C) 2022 Université Paul Sabatier - IRIT - * Copyright (C) 2022 Université Paul Sabatier - Laplace - * - * 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/>. */ - -#ifndef SHITRAN_H -#define SHITRAN_H - -#include <rsys/rsys.h> - -/* Library symbol management */ -#if defined(SHITRAN_SHARED_BUILD) /* Build shared library */ - #define SHITRAN_API extern EXPORT_SYM -#elif defined(SHITRAN_STATIC) /* Use/build static library */ - #define SHITRAN_API extern LOCAL_SYM -#else - #define SHITRAN_API extern IMPORT_SYM -#endif - -/* Helper macro that asserts if the invocation of the sth function `Func' - * returns an error. One should use this macro on sth function calls for - * which no explicit error checking is performed */ -#ifndef NDEBUG - #define SHITRAN(Func) ASSERT(shitran_ ## Func == RES_OK) -#else - #define SHITRAN(Func) shitran_ ## Func -#endif - -struct shitran_create_args { - struct logger* logger; /* May be NULL <=> default logger */ - struct mem_allocator* allocator; /* NULL <=> use default allocator */ - int verbose; /* Verbosity level */ -}; -#define SHITRAN_CREATE_ARGS_DEFAULT__ {NULL, NULL, 0} -static const struct shitran_create_args SHITRAN_CREATE_ARGS_DEFAULT = - SHITRAN_CREATE_ARGS_DEFAULT__; - -/* Forware declarations */ -struct shitran; -struct shitran_isotopologues; - -BEGIN_DECLS - -/******************************************************************************* - * Device API - ******************************************************************************/ -SHITRAN_API res_T -shitran_create - (const struct shitran_create_args* args, - struct shitran** shitran); - -SHITRAN_API res_T -shitran_ref_get - (struct shitran* shitran); - -SHITRAN_API res_T -shitran_ref_put - (struct shitran* shitran); - -/******************************************************************************* - * Isotopologues API - ******************************************************************************/ -SHITRAN_API res_T -shitran_isotopologues_load - (struct shitran* shitran, - const char* path, - struct shitran_isotopologues** isotopologues); - -SHITRAN_API res_T -shitran_isotopologues_load_from_stream - (struct shitran* shitran, - FILE* stream, - const char* stream_name, /* NULL <=> use default stream name */ - struct shitran_isotopologues** isotopologues); - -SHITRAN_API res_T -shitran_isotopologues_ref_get - (struct shitran_isotopologues* isotopologues); - -SHITRAN_API res_T -shitran_isotopologues_ref_put - (struct shitran_isotopologues* isotopologues); - -END_DECLS - -#endif /* SHITRAN_H */ diff --git a/src/shitran_c.h b/src/shitran_c.h @@ -1,35 +0,0 @@ -/* Copyright (C) 2022 CNRS - LMD - * Copyright (C) 2022 |Meso|Star> (contact@meso-star.com) - * Copyright (C) 2022 Université Paul Sabatier - IRIT - * Copyright (C) 2022 Université Paul Sabatier - Laplace - * - * 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/>. */ - -#ifndef SHITRAN_C_H -#define SHITRAN_C_H - -#include <rsys/logger.h> -#include <rsys/ref_count.h> - -struct mem_allocator; - -struct shitran { - struct mem_allocator* allocator; - struct logger* logger; - struct logger logger__; /* Default logger */ - int verbose; - ref_T ref; -}; - -#endif /* SHITRAN_C_H */ diff --git a/src/shitran_isotopologues.c b/src/shitran_isotopologues.c @@ -1,426 +0,0 @@ -/* Copyright (C) 2022 CNRS - LMD - * Copyright (C) 2022 |Meso|Star> (contact@meso-star.com) - * Copyright (C) 2022 Université Paul Sabatier - IRIT - * Copyright (C) 2022 Université Paul Sabatier - Laplace - * - * 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 support */ - -#include "shitran.h" -#include "shitran_c.h" -#include "shitran_log.h" - -#include <rsys/cstr.h> -#include <rsys/dynamic_array.h> -#include <rsys/hash_table.h> -#include <rsys/ref_count.h> -#include <rsys/str.h> -#include <rsys/text_reader.h> - -#include <ctype.h> -#include <string.h> - -struct isotope { - double abundance; - double Q; /* At 296 K */ - double gj; - double molar_mass; /* In g */ - size_t molecule; /* Index of the molecule to which the isotope belongs */ - int id; /* Unique identifier of the isotope */ -}; - -/* Generate the dynamic array of isotopes */ -#define DARRAY_NAME isotope -#define DARRAY_DATA struct isotope -#include <rsys/dynamic_array.h> - -struct molecule { - struct str name; - size_t isotopes_range[2]; /* Range of the 1st and last regisered isotopes */ - int id; /* Unique identifier of the molecule */ -}; -#define MOLECULE_IS_VALID(Molecule) ((Molecule)->id >= 0) - -static INLINE void -molecule_clear(struct molecule* molecule) -{ - ASSERT(molecule); - molecule->isotopes_range[0] = SIZE_MAX; - molecule->isotopes_range[1] = 0; - molecule->id = -1; -} - -static INLINE void -molecule_init(struct mem_allocator* allocator, struct molecule* molecule) -{ - str_init(allocator, &molecule->name); - molecule_clear(molecule); -} - -static INLINE void -molecule_release(struct molecule* molecule) -{ - str_release(&molecule->name); -} - -static INLINE res_T -molecule_copy(struct molecule* dst, const struct molecule* src) -{ - dst->isotopes_range[0] = src->isotopes_range[0]; - dst->isotopes_range[1] = src->isotopes_range[1]; - dst->id = src->id; - return str_copy(&dst->name, &src->name); -} - -static INLINE res_T -molecule_copy_and_release(struct molecule* dst, struct molecule* src) -{ - dst->isotopes_range[0] = src->isotopes_range[0]; - dst->isotopes_range[1] = src->isotopes_range[1]; - dst->id = src->id; - return str_copy_and_release(&dst->name, &src->name); -} - -/* Generate the dynamic array of molecules */ -#define DARRAY_NAME molecule -#define DARRAY_DATA struct molecule -#define DARRAY_FUNCTOR_INIT molecule_init -#define DARRAY_FUNCTOR_RELEASE molecule_release -#define DARRAY_FUNCTOR_COPY molecule_copy -#define DARRAY_FUNCTOR_COPY_AND_RELEASE molecule_copy_and_release -#include <rsys/dynamic_array.h> - -/* Generate the hash table that map a unique identifier to its index */ -#define HTABLE_NAME id2entry -#define HTABLE_KEY int /* Unique identifier */ -#define HTABLE_DATA size_t /* Index of the corresponding registered data */ -#include <rsys/hash_table.h> - -struct shitran_isotopologues { - - /* List of molecules and isotopes */ - struct darray_molecule molecules; - struct darray_isotope isotopes; - - /* Map the identifier of a molecule/isotope to its correspond index into - * their corresponding dynamic arays into which they are registered */ - struct htable_id2entry molid2idx; - struct htable_id2entry isoid2idx; - - struct shitran* shitran; - ref_T ref; -}; - -/******************************************************************************* - * Helper functions - ******************************************************************************/ -static res_T -create_isotoplogues - (struct shitran* shitran, - struct shitran_isotopologues** out_isotopologues) -{ - struct shitran_isotopologues* isotopologues = NULL; - res_T res = RES_OK; - ASSERT(shitran && out_isotopologues); - - isotopologues = MEM_CALLOC(shitran->allocator, 1, sizeof(*isotopologues)); - if(!isotopologues) { - log_err(shitran, "Could not allocate the isotopologues data structure.\n"); - res = RES_MEM_ERR; - goto error; - } - ref_init(&isotopologues->ref); - SHITRAN(ref_get(shitran)); - isotopologues->shitran = shitran; - darray_molecule_init(shitran->allocator, &isotopologues->molecules); - darray_isotope_init(shitran->allocator, &isotopologues->isotopes); - htable_id2entry_init(shitran->allocator, &isotopologues->molid2idx); - htable_id2entry_init(shitran->allocator, &isotopologues->isoid2idx); - -exit: - *out_isotopologues = isotopologues; - return res; -error: - goto exit; -} - -static res_T -flush_molecule - (struct shitran_isotopologues* isotopologues, - struct molecule* molecule, /* Currently parsed molecule */ - struct txtrdr* txtrdr) -{ - size_t entry = 0; - res_T res = RES_OK; - ASSERT(isotopologues && molecule && MOLECULE_IS_VALID(molecule)); - - /* Fetch _exclusive_ upper bound */ - molecule->isotopes_range[1] = darray_isotope_size_get(&isotopologues->isotopes); - if(molecule->isotopes_range[0] >= molecule->isotopes_range[1]) { - log_warn(isotopologues->shitran, - "%s: the %s molecule does not have any isotopes.\n", - txtrdr_get_name(txtrdr), str_cget(&molecule->name)); - } - - /* Fetch the index of the registered molecule */ - entry = darray_molecule_size_get(&isotopologues->molecules); - - /* Storing the molecule */ - res = darray_molecule_push_back(&isotopologues->molecules, molecule); - if(res != RES_OK) { - log_err(isotopologues->shitran, - "%s: error storing the %s molecule -- %s.\n", - txtrdr_get_name(txtrdr), str_cget(&molecule->name), res_to_cstr(res)); - goto error; - } - - /* Registering the molecule */ - ASSERT(!htable_id2entry_find(&isotopologues->molid2idx, &molecule->id)); - res = htable_id2entry_set(&isotopologues->molid2idx, &molecule->id, &entry); - if(res != RES_OK) { - log_err(isotopologues->shitran, - "%s: error registering the %s molecule -- %s.\n", - txtrdr_get_name(txtrdr), str_cget(&molecule->name), res_to_cstr(res)); - goto error; - } - - molecule_clear(molecule); - -exit: - return res; -error: - goto exit; -} - -static res_T -parse_molecule - (struct shitran_isotopologues* isotopologues, - struct molecule* molecule, - struct txtrdr* txtrdr) -{ - char* name = NULL; - char* id = NULL; - char* tk = NULL; - char* tk_ctx = NULL; - size_t len; - res_T res = RES_OK; - ASSERT(molecule && txtrdr); - - name = strtok_r(txtrdr_get_line(txtrdr), " \t", &tk_ctx); - id = strtok_r(NULL, " \t", &tk_ctx); - - if(!name) { - log_err(isotopologues->shitran, "%s:%lu: molecule name is missing.\n", - txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr)); - res = RES_BAD_ARG; - goto error; - } - - len = strlen(id); - if(!id || !len || id[0] != '(' || id[len-1] != ')') { - log_err(isotopologues->shitran, "%s:%lu: invalid molecule identifier.\n", - txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr)); - res = RES_BAD_ARG; - goto error; - } - - id[len-1] = '\0'; /* Rm trailing parenthesis */ - res = cstr_to_int(id+1/*Rm leading parenthesis*/, &molecule->id); - if(res != RES_OK || !MOLECULE_IS_VALID(molecule)) { - id[len-1] = ')'; /* Re-add the trailing parenthesis */ - log_err(isotopologues->shitran, "%s:%lu: invalid molecule identifier `%s'.\n", - txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr), id); - res = RES_BAD_ARG; - goto error; - } - - tk = strtok_r(NULL, " \t", &tk_ctx); - if(tk) { - log_warn(isotopologues->shitran, "%s:%lu: unexpected text `%s'.\n", - txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr), tk); - } - -exit: - return res; -error: - goto exit; -} - -static res_T -parse_line - (struct shitran_isotopologues* isotopologues, - struct molecule* molecule, /* Currently parsed molecule */ - struct txtrdr* txtrdr) -{ - const char* line = NULL; - size_t i; - res_T res = RES_OK; - ASSERT(isotopologues && molecule && txtrdr); - - line = txtrdr_get_cline(txtrdr); - ASSERT(line); - i = strcspn(line, " \t"); - ASSERT(i < strlen(line)); - - if(isalpha(line[i])) { - if(MOLECULE_IS_VALID(molecule)) { - res = flush_molecule(isotopologues, molecule, txtrdr); - if(res != RES_OK) goto error; - } - res = parse_molecule(isotopologues, molecule, txtrdr); - if(res != RES_OK) goto error; - } else { - /* TODO parse the isotope */ - } - -exit: - return res; -error: - goto exit; -} - -static res_T -load_stream - (struct shitran* shitran, - FILE* stream, - const char* name, - struct shitran_isotopologues** out_isotopologues) -{ - struct molecule molecule; /* Current molecule */ - struct shitran_isotopologues* isotopologues = NULL; - struct txtrdr* txtrdr = NULL; - res_T res = RES_OK; - ASSERT(shitran && stream && name && out_isotopologues); - - molecule_init(shitran->allocator, &molecule); - - res = create_isotoplogues(shitran, &isotopologues); - if(res != RES_OK) goto error; - - res = txtrdr_stream(isotopologues->shitran->allocator, stream, name, - 0/*comment char*/, &txtrdr); - if(res != RES_OK) { - log_err(shitran, "%s: error creating the text reader -- %s.\n", - name, res_to_cstr(res)); - goto error; - } - - #define READ_LINE { \ - res = txtrdr_read_line(txtrdr); \ - if(res != RES_OK) { \ - log_err(shitran, "%s: error reading the line `%lu' -- %s.\n", \ - name, (unsigned long)txtrdr_get_line_num(txtrdr), res_to_cstr(res)); \ - goto error; \ - } \ - } (void)0 - - /* Skip the 1st line that is a comment line*/ - READ_LINE; - if(!txtrdr_get_cline(txtrdr)) goto exit; - - for(;;) { - READ_LINE; - - if(!txtrdr_get_cline(txtrdr)) break; /* No more parsed line */ - res = parse_line(isotopologues, &molecule, txtrdr); - if(res != RES_OK) goto error; - } - #undef READ_LINE - -exit: - *out_isotopologues = isotopologues; - molecule_release(&molecule); - return res; -error: - goto exit; -} - -static void -release_isotopologues(ref_T* ref) -{ - struct shitran* shitran = NULL; - struct shitran_isotopologues* isotopologues = CONTAINER_OF - (ref, struct shitran_isotopologues, ref); - ASSERT(ref); - shitran = isotopologues->shitran; - darray_molecule_release(&isotopologues->molecules); - darray_isotope_release(&isotopologues->isotopes); - htable_id2entry_release(&isotopologues->molid2idx); - htable_id2entry_release(&isotopologues->isoid2idx); - MEM_RM(shitran->allocator, isotopologues); - SHITRAN(ref_put(shitran)); -} - -/******************************************************************************* - * Exported functions - ******************************************************************************/ -res_T -shitran_isotopologues_load - (struct shitran* shitran, - const char* path, - struct shitran_isotopologues** isotopologues) -{ - FILE* file = NULL; - res_T res = RES_OK; - - if(!shitran || !path) { - res = RES_BAD_ARG; - goto error; - } - - file = fopen(path, "r"); - if(!file) { - log_err(shitran, "%s: error opening file `%s'.\n", FUNC_NAME, path); - res = RES_IO_ERR; - goto error; - } - - res = load_stream(shitran, file, path, isotopologues); - if(res != RES_OK) goto error; - -exit: - if(file) fclose(file); - return res; -error: - goto exit; -} - -res_T -shitran_isotopologues_load_from_stream - (struct shitran* shitran, - FILE* stream, - const char* stream_name, - struct shitran_isotopologues** isotopologues) -{ - if(!shitran || !stream) return RES_BAD_ARG; - return load_stream - (shitran, stream, stream_name ? stream_name : "<stream>", isotopologues); -} - -res_T -shitran_isotopologues_ref_get(struct shitran_isotopologues* isotopologues) -{ - if(!isotopologues) return RES_BAD_ARG; - ref_get(&isotopologues->ref); - return RES_OK; -} - -res_T -shitran_isotopologues_ref_put(struct shitran_isotopologues* isotopologues) -{ - if(!isotopologues) return RES_BAD_ARG; - ref_put(&isotopologues->ref, release_isotopologues); - return RES_OK; -} diff --git a/src/shitran_log.c b/src/shitran_log.c @@ -1,127 +0,0 @@ -/* Copyright (C) 2022 CNRS - LMD - * Copyright (C) 2022 |Meso|Star> (contact@meso-star.com) - * Copyright (C) 2022 Université Paul Sabatier - IRIT - * Copyright (C) 2022 Université Paul Sabatier - Laplace - * - * 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/>. */ - -#include "shitran_c.h" -#include "shitran_log.h" - -#include <rsys/cstr.h> -#include <rsys/logger.h> - -#include <stdarg.h> - -/******************************************************************************* - * Helper functions - ******************************************************************************/ -static INLINE void -log_msg - (const struct shitran* shitran, - const enum log_type stream, - const char* msg, - va_list vargs) -{ - ASSERT(shitran && msg); - if(shitran->verbose) { - res_T res; (void)res; - res = logger_vprint(shitran->logger, stream, msg, vargs); - ASSERT(res == RES_OK); - } -} - -static void -print_info(const char* msg, void* ctx) -{ - (void)ctx; - fprintf(stderr, MSG_INFO_PREFIX"%s", msg); -} - -static void -print_err(const char* msg, void* ctx) -{ - (void)ctx; - fprintf(stderr, MSG_ERROR_PREFIX"%s", msg); -} - -static void -print_warn(const char* msg, void* ctx) -{ - (void)ctx; - fprintf(stderr, MSG_WARNING_PREFIX"%s", msg); -} - -/******************************************************************************* - * Local functions - ******************************************************************************/ -res_T -setup_log_default(struct shitran* shitran) -{ - res_T res = RES_OK; - ASSERT(shitran); - - res = logger_init(shitran->allocator, &shitran->logger__); - if(res != RES_OK) { - if(shitran->verbose) { - fprintf(stderr, - MSG_ERROR_PREFIX - "Could not setup the default logger for the Star-HITRAN library -- %s.\n", - res_to_cstr(res)); - } - goto error; - } - logger_set_stream(&shitran->logger__, LOG_OUTPUT, print_info, NULL); - logger_set_stream(&shitran->logger__, LOG_ERROR, print_err, NULL); - logger_set_stream(&shitran->logger__, LOG_WARNING, print_warn, NULL); - shitran->logger = &shitran->logger__; - -exit: - return res; -error: - goto exit; -} - -void -log_info(const struct shitran* shitran, const char* msg, ...) -{ - va_list vargs_list; - ASSERT(shitran && msg); - - va_start(vargs_list, msg); - log_msg(shitran, LOG_OUTPUT, msg, vargs_list); - va_end(vargs_list); -} - -void -log_err(const struct shitran* shitran, const char* msg, ...) -{ - va_list vargs_list; - ASSERT(shitran && msg); - - va_start(vargs_list, msg); - log_msg(shitran, LOG_ERROR, msg, vargs_list); - va_end(vargs_list); -} - -void -log_warn(const struct shitran* shitran, const char* msg, ...) -{ - va_list vargs_list; - ASSERT(shitran && msg); - - va_start(vargs_list, msg); - log_msg(shitran, LOG_WARNING, msg, vargs_list); - va_end(vargs_list); -} diff --git a/src/shitran_log.h b/src/shitran_log.h @@ -1,73 +0,0 @@ -/* Copyright (C) 2022 CNRS - LMD - * Copyright (C) 2022 |Meso|Star> (contact@meso-star.com) - * Copyright (C) 2022 Université Paul Sabatier - IRIT - * Copyright (C) 2022 Université Paul Sabatier - Laplace - * - * 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/>. */ - -#ifndef SHITRAN_LOG_H -#define SHITRAN_LOG_H - -#include <rsys/rsys.h> - -#define MSG_INFO_PREFIX "Star-HITRAN:\x1b[1m\x1b[32minfo\x1b[0m: " -#define MSG_ERROR_PREFIX "Star-HITRAN:\x1b[1m\x1b[31merror\x1b[0m: " -#define MSG_WARNING_PREFIX "Star-HITRAN:\x1b[1m\x1b[33mwarning\x1b[0m: " - -struct shitran; -struct logger; - -extern LOCAL_SYM res_T -setup_log_default - (struct shitran* shitran); - -/* Conditionally log a message on the LOG_OUTPUT stream of the shitran logger, - * with respect to its verbose flag */ -extern LOCAL_SYM void -log_info - (const struct shitran* shitran, - const char* msg, - ...) -#ifdef COMPILER_GCC - __attribute((format(printf, 2, 3))) -#endif -; - -/* Conditionally log a message on the LOG_ERROR stream of the shitran logger, - * with respect to its verbose flag */ -extern LOCAL_SYM void -log_err - (const struct shitran* shitran, - const char* msg, - ...) -#ifdef COMPILER_GCC - __attribute((format(printf, 2, 3))) -#endif -; - -/* Conditionally log a message on the LOG_WARNING stream of the shitran logger, - * with respect to its verbose flag */ -extern LOCAL_SYM void -log_warn - (const struct shitran* shitran, - const char* msg, - ...) -#ifdef COMPILER_GCC - __attribute((format(printf, 2, 3))) -#endif -; - - -#endif /* SHITRAN_LOG_H */ - diff --git a/src/sht.c b/src/sht.c @@ -0,0 +1,101 @@ +/* Copyright (C) 2022 CNRS - LMD + * Copyright (C) 2022 |Meso|Star> (contact@meso-star.com) + * Copyright (C) 2022 Université Paul Sabatier - IRIT + * Copyright (C) 2022 Université Paul Sabatier - Laplace + * + * 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/>. */ + +#include "sht.h" +#include "sht_c.h" +#include "sht_log.h" + +/******************************************************************************* + * Helper functions + ******************************************************************************/ +static INLINE res_T +check_sht_create_args(const struct sht_create_args* args) +{ + return args ? RES_OK : RES_BAD_ARG; +} + +static void +release_sht(ref_T* ref) +{ + struct sht* sht = CONTAINER_OF(ref, struct sht, ref); + ASSERT(ref); + if(sht->logger == &sht->logger__) logger_release(&sht->logger__); + MEM_RM(sht->allocator, sht); +} + +/******************************************************************************* + * Exported functions + ******************************************************************************/ +res_T +sht_create + (const struct sht_create_args* args, + struct sht** out_sht) +{ + struct mem_allocator* allocator = NULL; + struct sht* sht = NULL; + res_T res = RES_OK; + + if(!out_sht) { res = RES_BAD_ARG; goto error; } + res = check_sht_create_args(args); + if(res != RES_OK) goto error; + + allocator = args->allocator ? args->allocator : &mem_default_allocator; + sht = MEM_CALLOC(allocator, 1, sizeof(*sht)); + if(!sht) { + #define ERR_STR "Could not allocate the Star-HITRAN data structure.\n" + if(args->logger) { + logger_print(args->logger, LOG_ERROR, ERR_STR); + } else { + fprintf(stderr, MSG_ERROR_PREFIX ERR_STR); + } + #undef ERR_STR + res = RES_MEM_ERR; + goto error; + } + ref_init(&sht->ref); + sht->allocator = allocator; + sht->verbose = args->verbose; + if(args->logger) { + sht->logger = args->logger; + } else { + setup_log_default(sht); + } + +exit: + if(out_sht) *out_sht = sht; + return res; +error: + if(sht) { SHT(ref_put(sht)); sht = NULL; } + goto exit; +} + +res_T +sht_ref_get(struct sht* sht) +{ + if(!sht) return RES_BAD_ARG; + ref_get(&sht->ref); + return RES_OK; +} + +res_T +sht_ref_put(struct sht* sht) +{ + if(!sht) return RES_BAD_ARG; + ref_put(&sht->ref, release_sht); + return RES_OK; +} diff --git a/src/sht.h b/src/sht.h @@ -0,0 +1,99 @@ +/* Copyright (C) 2022 CNRS - LMD + * Copyright (C) 2022 |Meso|Star> (contact@meso-star.com) + * Copyright (C) 2022 Université Paul Sabatier - IRIT + * Copyright (C) 2022 Université Paul Sabatier - Laplace + * + * 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/>. */ + +#ifndef SHT_H +#define SHT_H + +#include <rsys/rsys.h> + +/* Library symbol management */ +#if defined(SHT_SHARED_BUILD) /* Build shared library */ + #define SHT_API extern EXPORT_SYM +#elif defined(SHT_STATIC) /* Use/build static library */ + #define SHT_API extern LOCAL_SYM +#else + #define SHT_API extern IMPORT_SYM +#endif + +/* Helper macro that asserts if the invocation of the sth function `Func' + * returns an error. One should use this macro on sth function calls for + * which no explicit error checking is performed */ +#ifndef NDEBUG + #define SHT(Func) ASSERT(sht_ ## Func == RES_OK) +#else + #define SHT(Func) sht_ ## Func +#endif + +struct sht_create_args { + struct logger* logger; /* May be NULL <=> default logger */ + struct mem_allocator* allocator; /* NULL <=> use default allocator */ + int verbose; /* Verbosity level */ +}; +#define SHT_CREATE_ARGS_DEFAULT__ {NULL, NULL, 0} +static const struct sht_create_args SHT_CREATE_ARGS_DEFAULT = + SHT_CREATE_ARGS_DEFAULT__; + +/* Forware declarations */ +struct sht; +struct sht_isotopologues; + +BEGIN_DECLS + +/******************************************************************************* + * Device API + ******************************************************************************/ +SHT_API res_T +sht_create + (const struct sht_create_args* args, + struct sht** sht); + +SHT_API res_T +sht_ref_get + (struct sht* sht); + +SHT_API res_T +sht_ref_put + (struct sht* sht); + +/******************************************************************************* + * Isotopologues API + ******************************************************************************/ +SHT_API res_T +sht_isotopologues_load + (struct sht* sht, + const char* path, + struct sht_isotopologues** isotopologues); + +SHT_API res_T +sht_isotopologues_load_from_stream + (struct sht* sht, + FILE* stream, + const char* stream_name, /* NULL <=> use default stream name */ + struct sht_isotopologues** isotopologues); + +SHT_API res_T +sht_isotopologues_ref_get + (struct sht_isotopologues* isotopologues); + +SHT_API res_T +sht_isotopologues_ref_put + (struct sht_isotopologues* isotopologues); + +END_DECLS + +#endif /* SHT_H */ diff --git a/src/sht_c.h b/src/sht_c.h @@ -0,0 +1,35 @@ +/* Copyright (C) 2022 CNRS - LMD + * Copyright (C) 2022 |Meso|Star> (contact@meso-star.com) + * Copyright (C) 2022 Université Paul Sabatier - IRIT + * Copyright (C) 2022 Université Paul Sabatier - Laplace + * + * 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/>. */ + +#ifndef SHT_C_H +#define SHT_C_H + +#include <rsys/logger.h> +#include <rsys/ref_count.h> + +struct mem_allocator; + +struct sht { + struct mem_allocator* allocator; + struct logger* logger; + struct logger logger__; /* Default logger */ + int verbose; + ref_T ref; +}; + +#endif /* SHT_C_H */ diff --git a/src/sht_isotopologues.c b/src/sht_isotopologues.c @@ -0,0 +1,426 @@ +/* Copyright (C) 2022 CNRS - LMD + * Copyright (C) 2022 |Meso|Star> (contact@meso-star.com) + * Copyright (C) 2022 Université Paul Sabatier - IRIT + * Copyright (C) 2022 Université Paul Sabatier - Laplace + * + * 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 support */ + +#include "sht.h" +#include "sht_c.h" +#include "sht_log.h" + +#include <rsys/cstr.h> +#include <rsys/dynamic_array.h> +#include <rsys/hash_table.h> +#include <rsys/ref_count.h> +#include <rsys/str.h> +#include <rsys/text_reader.h> + +#include <ctype.h> +#include <string.h> + +struct isotope { + double abundance; + double Q; /* At 296 K */ + double gj; + double molar_mass; /* In g */ + size_t molecule; /* Index of the molecule to which the isotope belongs */ + int id; /* Unique identifier of the isotope */ +}; + +/* Generate the dynamic array of isotopes */ +#define DARRAY_NAME isotope +#define DARRAY_DATA struct isotope +#include <rsys/dynamic_array.h> + +struct molecule { + struct str name; + size_t isotopes_range[2]; /* Range of the 1st and last regisered isotopes */ + int id; /* Unique identifier of the molecule */ +}; +#define MOLECULE_IS_VALID(Molecule) ((Molecule)->id >= 0) + +static INLINE void +molecule_clear(struct molecule* molecule) +{ + ASSERT(molecule); + molecule->isotopes_range[0] = SIZE_MAX; + molecule->isotopes_range[1] = 0; + molecule->id = -1; +} + +static INLINE void +molecule_init(struct mem_allocator* allocator, struct molecule* molecule) +{ + str_init(allocator, &molecule->name); + molecule_clear(molecule); +} + +static INLINE void +molecule_release(struct molecule* molecule) +{ + str_release(&molecule->name); +} + +static INLINE res_T +molecule_copy(struct molecule* dst, const struct molecule* src) +{ + dst->isotopes_range[0] = src->isotopes_range[0]; + dst->isotopes_range[1] = src->isotopes_range[1]; + dst->id = src->id; + return str_copy(&dst->name, &src->name); +} + +static INLINE res_T +molecule_copy_and_release(struct molecule* dst, struct molecule* src) +{ + dst->isotopes_range[0] = src->isotopes_range[0]; + dst->isotopes_range[1] = src->isotopes_range[1]; + dst->id = src->id; + return str_copy_and_release(&dst->name, &src->name); +} + +/* Generate the dynamic array of molecules */ +#define DARRAY_NAME molecule +#define DARRAY_DATA struct molecule +#define DARRAY_FUNCTOR_INIT molecule_init +#define DARRAY_FUNCTOR_RELEASE molecule_release +#define DARRAY_FUNCTOR_COPY molecule_copy +#define DARRAY_FUNCTOR_COPY_AND_RELEASE molecule_copy_and_release +#include <rsys/dynamic_array.h> + +/* Generate the hash table that map a unique identifier to its index */ +#define HTABLE_NAME id2entry +#define HTABLE_KEY int /* Unique identifier */ +#define HTABLE_DATA size_t /* Index of the corresponding registered data */ +#include <rsys/hash_table.h> + +struct sht_isotopologues { + + /* List of molecules and isotopes */ + struct darray_molecule molecules; + struct darray_isotope isotopes; + + /* Map the identifier of a molecule/isotope to its correspond index into + * their corresponding dynamic arays into which they are registered */ + struct htable_id2entry molid2idx; + struct htable_id2entry isoid2idx; + + struct sht* sht; + ref_T ref; +}; + +/******************************************************************************* + * Helper functions + ******************************************************************************/ +static res_T +create_isotoplogues + (struct sht* sht, + struct sht_isotopologues** out_isotopologues) +{ + struct sht_isotopologues* isotopologues = NULL; + res_T res = RES_OK; + ASSERT(sht && out_isotopologues); + + isotopologues = MEM_CALLOC(sht->allocator, 1, sizeof(*isotopologues)); + if(!isotopologues) { + log_err(sht, "Could not allocate the isotopologues data structure.\n"); + res = RES_MEM_ERR; + goto error; + } + ref_init(&isotopologues->ref); + SHT(ref_get(sht)); + isotopologues->sht = sht; + darray_molecule_init(sht->allocator, &isotopologues->molecules); + darray_isotope_init(sht->allocator, &isotopologues->isotopes); + htable_id2entry_init(sht->allocator, &isotopologues->molid2idx); + htable_id2entry_init(sht->allocator, &isotopologues->isoid2idx); + +exit: + *out_isotopologues = isotopologues; + return res; +error: + goto exit; +} + +static res_T +flush_molecule + (struct sht_isotopologues* isotopologues, + struct molecule* molecule, /* Currently parsed molecule */ + struct txtrdr* txtrdr) +{ + size_t entry = 0; + res_T res = RES_OK; + ASSERT(isotopologues && molecule && MOLECULE_IS_VALID(molecule)); + + /* Fetch _exclusive_ upper bound */ + molecule->isotopes_range[1] = darray_isotope_size_get(&isotopologues->isotopes); + if(molecule->isotopes_range[0] >= molecule->isotopes_range[1]) { + log_warn(isotopologues->sht, + "%s: the %s molecule does not have any isotopes.\n", + txtrdr_get_name(txtrdr), str_cget(&molecule->name)); + } + + /* Fetch the index of the registered molecule */ + entry = darray_molecule_size_get(&isotopologues->molecules); + + /* Storing the molecule */ + res = darray_molecule_push_back(&isotopologues->molecules, molecule); + if(res != RES_OK) { + log_err(isotopologues->sht, + "%s: error storing the %s molecule -- %s.\n", + txtrdr_get_name(txtrdr), str_cget(&molecule->name), res_to_cstr(res)); + goto error; + } + + /* Registering the molecule */ + ASSERT(!htable_id2entry_find(&isotopologues->molid2idx, &molecule->id)); + res = htable_id2entry_set(&isotopologues->molid2idx, &molecule->id, &entry); + if(res != RES_OK) { + log_err(isotopologues->sht, + "%s: error registering the %s molecule -- %s.\n", + txtrdr_get_name(txtrdr), str_cget(&molecule->name), res_to_cstr(res)); + goto error; + } + + molecule_clear(molecule); + +exit: + return res; +error: + goto exit; +} + +static res_T +parse_molecule + (struct sht_isotopologues* isotopologues, + struct molecule* molecule, + struct txtrdr* txtrdr) +{ + char* name = NULL; + char* id = NULL; + char* tk = NULL; + char* tk_ctx = NULL; + size_t len; + res_T res = RES_OK; + ASSERT(molecule && txtrdr); + + name = strtok_r(txtrdr_get_line(txtrdr), " \t", &tk_ctx); + id = strtok_r(NULL, " \t", &tk_ctx); + + if(!name) { + log_err(isotopologues->sht, "%s:%lu: molecule name is missing.\n", + txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr)); + res = RES_BAD_ARG; + goto error; + } + + len = strlen(id); + if(!id || !len || id[0] != '(' || id[len-1] != ')') { + log_err(isotopologues->sht, "%s:%lu: invalid molecule identifier.\n", + txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr)); + res = RES_BAD_ARG; + goto error; + } + + id[len-1] = '\0'; /* Rm trailing parenthesis */ + res = cstr_to_int(id+1/*Rm leading parenthesis*/, &molecule->id); + if(res != RES_OK || !MOLECULE_IS_VALID(molecule)) { + id[len-1] = ')'; /* Re-add the trailing parenthesis */ + log_err(isotopologues->sht, "%s:%lu: invalid molecule identifier `%s'.\n", + txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr), id); + res = RES_BAD_ARG; + goto error; + } + + tk = strtok_r(NULL, " \t", &tk_ctx); + if(tk) { + log_warn(isotopologues->sht, "%s:%lu: unexpected text `%s'.\n", + txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr), tk); + } + +exit: + return res; +error: + goto exit; +} + +static res_T +parse_line + (struct sht_isotopologues* isotopologues, + struct molecule* molecule, /* Currently parsed molecule */ + struct txtrdr* txtrdr) +{ + const char* line = NULL; + size_t i; + res_T res = RES_OK; + ASSERT(isotopologues && molecule && txtrdr); + + line = txtrdr_get_cline(txtrdr); + ASSERT(line); + i = strcspn(line, " \t"); + ASSERT(i < strlen(line)); + + if(isalpha(line[i])) { + if(MOLECULE_IS_VALID(molecule)) { + res = flush_molecule(isotopologues, molecule, txtrdr); + if(res != RES_OK) goto error; + } + res = parse_molecule(isotopologues, molecule, txtrdr); + if(res != RES_OK) goto error; + } else { + /* TODO parse the isotope */ + } + +exit: + return res; +error: + goto exit; +} + +static res_T +load_stream + (struct sht* sht, + FILE* stream, + const char* name, + struct sht_isotopologues** out_isotopologues) +{ + struct molecule molecule; /* Current molecule */ + struct sht_isotopologues* isotopologues = NULL; + struct txtrdr* txtrdr = NULL; + res_T res = RES_OK; + ASSERT(sht && stream && name && out_isotopologues); + + molecule_init(sht->allocator, &molecule); + + res = create_isotoplogues(sht, &isotopologues); + if(res != RES_OK) goto error; + + res = txtrdr_stream(isotopologues->sht->allocator, stream, name, + 0/*comment char*/, &txtrdr); + if(res != RES_OK) { + log_err(sht, "%s: error creating the text reader -- %s.\n", + name, res_to_cstr(res)); + goto error; + } + + #define READ_LINE { \ + res = txtrdr_read_line(txtrdr); \ + if(res != RES_OK) { \ + log_err(sht, "%s: error reading the line `%lu' -- %s.\n", \ + name, (unsigned long)txtrdr_get_line_num(txtrdr), res_to_cstr(res)); \ + goto error; \ + } \ + } (void)0 + + /* Skip the 1st line that is a comment line*/ + READ_LINE; + if(!txtrdr_get_cline(txtrdr)) goto exit; + + for(;;) { + READ_LINE; + + if(!txtrdr_get_cline(txtrdr)) break; /* No more parsed line */ + res = parse_line(isotopologues, &molecule, txtrdr); + if(res != RES_OK) goto error; + } + #undef READ_LINE + +exit: + *out_isotopologues = isotopologues; + molecule_release(&molecule); + return res; +error: + goto exit; +} + +static void +release_isotopologues(ref_T* ref) +{ + struct sht* sht = NULL; + struct sht_isotopologues* isotopologues = CONTAINER_OF + (ref, struct sht_isotopologues, ref); + ASSERT(ref); + sht = isotopologues->sht; + darray_molecule_release(&isotopologues->molecules); + darray_isotope_release(&isotopologues->isotopes); + htable_id2entry_release(&isotopologues->molid2idx); + htable_id2entry_release(&isotopologues->isoid2idx); + MEM_RM(sht->allocator, isotopologues); + SHT(ref_put(sht)); +} + +/******************************************************************************* + * Exported functions + ******************************************************************************/ +res_T +sht_isotopologues_load + (struct sht* sht, + const char* path, + struct sht_isotopologues** isotopologues) +{ + FILE* file = NULL; + res_T res = RES_OK; + + if(!sht || !path) { + res = RES_BAD_ARG; + goto error; + } + + file = fopen(path, "r"); + if(!file) { + log_err(sht, "%s: error opening file `%s'.\n", FUNC_NAME, path); + res = RES_IO_ERR; + goto error; + } + + res = load_stream(sht, file, path, isotopologues); + if(res != RES_OK) goto error; + +exit: + if(file) fclose(file); + return res; +error: + goto exit; +} + +res_T +sht_isotopologues_load_from_stream + (struct sht* sht, + FILE* stream, + const char* stream_name, + struct sht_isotopologues** isotopologues) +{ + if(!sht || !stream) return RES_BAD_ARG; + return load_stream + (sht, stream, stream_name ? stream_name : "<stream>", isotopologues); +} + +res_T +sht_isotopologues_ref_get(struct sht_isotopologues* isotopologues) +{ + if(!isotopologues) return RES_BAD_ARG; + ref_get(&isotopologues->ref); + return RES_OK; +} + +res_T +sht_isotopologues_ref_put(struct sht_isotopologues* isotopologues) +{ + if(!isotopologues) return RES_BAD_ARG; + ref_put(&isotopologues->ref, release_isotopologues); + return RES_OK; +} diff --git a/src/sht_log.c b/src/sht_log.c @@ -0,0 +1,127 @@ +/* Copyright (C) 2022 CNRS - LMD + * Copyright (C) 2022 |Meso|Star> (contact@meso-star.com) + * Copyright (C) 2022 Université Paul Sabatier - IRIT + * Copyright (C) 2022 Université Paul Sabatier - Laplace + * + * 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/>. */ + +#include "sht_c.h" +#include "sht_log.h" + +#include <rsys/cstr.h> +#include <rsys/logger.h> + +#include <stdarg.h> + +/******************************************************************************* + * Helper functions + ******************************************************************************/ +static INLINE void +log_msg + (const struct sht* sht, + const enum log_type stream, + const char* msg, + va_list vargs) +{ + ASSERT(sht && msg); + if(sht->verbose) { + res_T res; (void)res; + res = logger_vprint(sht->logger, stream, msg, vargs); + ASSERT(res == RES_OK); + } +} + +static void +print_info(const char* msg, void* ctx) +{ + (void)ctx; + fprintf(stderr, MSG_INFO_PREFIX"%s", msg); +} + +static void +print_err(const char* msg, void* ctx) +{ + (void)ctx; + fprintf(stderr, MSG_ERROR_PREFIX"%s", msg); +} + +static void +print_warn(const char* msg, void* ctx) +{ + (void)ctx; + fprintf(stderr, MSG_WARNING_PREFIX"%s", msg); +} + +/******************************************************************************* + * Local functions + ******************************************************************************/ +res_T +setup_log_default(struct sht* sht) +{ + res_T res = RES_OK; + ASSERT(sht); + + res = logger_init(sht->allocator, &sht->logger__); + if(res != RES_OK) { + if(sht->verbose) { + fprintf(stderr, + MSG_ERROR_PREFIX + "Could not setup the default logger for the Star-HITRAN library -- %s.\n", + res_to_cstr(res)); + } + goto error; + } + logger_set_stream(&sht->logger__, LOG_OUTPUT, print_info, NULL); + logger_set_stream(&sht->logger__, LOG_ERROR, print_err, NULL); + logger_set_stream(&sht->logger__, LOG_WARNING, print_warn, NULL); + sht->logger = &sht->logger__; + +exit: + return res; +error: + goto exit; +} + +void +log_info(const struct sht* sht, const char* msg, ...) +{ + va_list vargs_list; + ASSERT(sht && msg); + + va_start(vargs_list, msg); + log_msg(sht, LOG_OUTPUT, msg, vargs_list); + va_end(vargs_list); +} + +void +log_err(const struct sht* sht, const char* msg, ...) +{ + va_list vargs_list; + ASSERT(sht && msg); + + va_start(vargs_list, msg); + log_msg(sht, LOG_ERROR, msg, vargs_list); + va_end(vargs_list); +} + +void +log_warn(const struct sht* sht, const char* msg, ...) +{ + va_list vargs_list; + ASSERT(sht && msg); + + va_start(vargs_list, msg); + log_msg(sht, LOG_WARNING, msg, vargs_list); + va_end(vargs_list); +} diff --git a/src/sht_log.h b/src/sht_log.h @@ -0,0 +1,73 @@ +/* Copyright (C) 2022 CNRS - LMD + * Copyright (C) 2022 |Meso|Star> (contact@meso-star.com) + * Copyright (C) 2022 Université Paul Sabatier - IRIT + * Copyright (C) 2022 Université Paul Sabatier - Laplace + * + * 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/>. */ + +#ifndef SHT_LOG_H +#define SHT_LOG_H + +#include <rsys/rsys.h> + +#define MSG_INFO_PREFIX "Star-HITRAN:\x1b[1m\x1b[32minfo\x1b[0m: " +#define MSG_ERROR_PREFIX "Star-HITRAN:\x1b[1m\x1b[31merror\x1b[0m: " +#define MSG_WARNING_PREFIX "Star-HITRAN:\x1b[1m\x1b[33mwarning\x1b[0m: " + +struct sht; +struct logger; + +extern LOCAL_SYM res_T +setup_log_default + (struct sht* sht); + +/* Conditionally log a message on the LOG_OUTPUT stream of the sht logger, + * with respect to its verbose flag */ +extern LOCAL_SYM void +log_info + (const struct sht* sht, + const char* msg, + ...) +#ifdef COMPILER_GCC + __attribute((format(printf, 2, 3))) +#endif +; + +/* Conditionally log a message on the LOG_ERROR stream of the sht logger, + * with respect to its verbose flag */ +extern LOCAL_SYM void +log_err + (const struct sht* sht, + const char* msg, + ...) +#ifdef COMPILER_GCC + __attribute((format(printf, 2, 3))) +#endif +; + +/* Conditionally log a message on the LOG_WARNING stream of the sht logger, + * with respect to its verbose flag */ +extern LOCAL_SYM void +log_warn + (const struct sht* sht, + const char* msg, + ...) +#ifdef COMPILER_GCC + __attribute((format(printf, 2, 3))) +#endif +; + + +#endif /* SHT_LOG_H */ + diff --git a/src/test_shitran.c b/src/test_shitran.c @@ -1,74 +0,0 @@ -/* Copyright (C) 2022 CNRS - LMD - * Copyright (C) 2022 |Meso|Star> (contact@meso-star.com) - * Copyright (C) 2022 Université Paul Sabatier - IRIT - * Copyright (C) 2022 Université Paul Sabatier - Laplace - * - * 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/>. */ - -#include "shitran.h" - -#include <rsys/logger.h> - -static void -log_stream(const char* msg, void* ctx) -{ - ASSERT(msg); - (void)msg, (void)ctx; - printf("%s\n", msg); -} - -int -main(int argc, char** argv) -{ - struct mem_allocator allocator; - struct logger logger; - struct shitran* shitran; - struct shitran_create_args args = SHITRAN_CREATE_ARGS_DEFAULT; - (void)argc, (void)argv; - - CHK(shitran_create(NULL, &shitran) == RES_BAD_ARG); - CHK(shitran_create(&args, NULL) == RES_BAD_ARG); - CHK(shitran_create(&args, &shitran) == RES_OK); - - CHK(shitran_ref_get(NULL) == RES_BAD_ARG); - CHK(shitran_ref_get(shitran) == RES_OK); - CHK(shitran_ref_put(NULL) == RES_BAD_ARG); - CHK(shitran_ref_put(shitran) == RES_OK); - CHK(shitran_ref_put(shitran) == RES_OK); - - CHK(mem_init_proxy_allocator(&allocator, &mem_default_allocator) == RES_OK); - args.allocator = &allocator; - args.verbose = 1; - CHK(shitran_create(&args, &shitran) == RES_OK); - CHK(MEM_ALLOCATED_SIZE(&allocator) != 0); - CHK(shitran_ref_put(shitran) == RES_OK); - - CHK(logger_init(&allocator, &logger) == RES_OK); - logger_set_stream(&logger, LOG_OUTPUT, log_stream, NULL); - logger_set_stream(&logger, LOG_ERROR, log_stream, NULL); - logger_set_stream(&logger, LOG_WARNING, log_stream, NULL); - - args.logger = &logger; - CHK(shitran_create(&args, &shitran) == RES_OK); - CHK(shitran_ref_put(shitran) == RES_OK); - args.allocator = NULL; - CHK(shitran_create(&args, &shitran) == RES_OK); - CHK(shitran_ref_put(shitran) == RES_OK); - - logger_release(&logger); - CHK(MEM_ALLOCATED_SIZE(&allocator) == 0); - mem_shutdown_proxy_allocator(&allocator); - CHK(mem_allocated_size() == 0); - return 0; -} diff --git a/src/test_sht.c b/src/test_sht.c @@ -0,0 +1,74 @@ +/* Copyright (C) 2022 CNRS - LMD + * Copyright (C) 2022 |Meso|Star> (contact@meso-star.com) + * Copyright (C) 2022 Université Paul Sabatier - IRIT + * Copyright (C) 2022 Université Paul Sabatier - Laplace + * + * 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/>. */ + +#include "sht.h" + +#include <rsys/logger.h> + +static void +log_stream(const char* msg, void* ctx) +{ + ASSERT(msg); + (void)msg, (void)ctx; + printf("%s\n", msg); +} + +int +main(int argc, char** argv) +{ + struct mem_allocator allocator; + struct logger logger; + struct sht* sht; + struct sht_create_args args = SHT_CREATE_ARGS_DEFAULT; + (void)argc, (void)argv; + + CHK(sht_create(NULL, &sht) == RES_BAD_ARG); + CHK(sht_create(&args, NULL) == RES_BAD_ARG); + CHK(sht_create(&args, &sht) == RES_OK); + + CHK(sht_ref_get(NULL) == RES_BAD_ARG); + CHK(sht_ref_get(sht) == RES_OK); + CHK(sht_ref_put(NULL) == RES_BAD_ARG); + CHK(sht_ref_put(sht) == RES_OK); + CHK(sht_ref_put(sht) == RES_OK); + + CHK(mem_init_proxy_allocator(&allocator, &mem_default_allocator) == RES_OK); + args.allocator = &allocator; + args.verbose = 1; + CHK(sht_create(&args, &sht) == RES_OK); + CHK(MEM_ALLOCATED_SIZE(&allocator) != 0); + CHK(sht_ref_put(sht) == RES_OK); + + CHK(logger_init(&allocator, &logger) == RES_OK); + logger_set_stream(&logger, LOG_OUTPUT, log_stream, NULL); + logger_set_stream(&logger, LOG_ERROR, log_stream, NULL); + logger_set_stream(&logger, LOG_WARNING, log_stream, NULL); + + args.logger = &logger; + CHK(sht_create(&args, &sht) == RES_OK); + CHK(sht_ref_put(sht) == RES_OK); + args.allocator = NULL; + CHK(sht_create(&args, &sht) == RES_OK); + CHK(sht_ref_put(sht) == RES_OK); + + logger_release(&logger); + CHK(MEM_ALLOCATED_SIZE(&allocator) == 0); + mem_shutdown_proxy_allocator(&allocator); + CHK(mem_allocated_size() == 0); + return 0; +}