rnsl

Load a list of strings expanded by the shell
git clone git://git.meso-star.fr/rnsl.git
Log | Files | Refs | README | LICENSE

commit 2498b39a057ff8b136541d3ad80c9b275923e121
parent 06510eca3e87cb3f83ab86655736bda772c130a6
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Tue, 20 Sep 2022 09:57:13 +0200

Rename the library

Diffstat:
MREADME.md | 6+++---
Mcmake/CMakeLists.txt | 54+++++++++++++++++++++++++++---------------------------
Dsrc/rnfl.c | 110-------------------------------------------------------------------------------
Dsrc/rnfl.h | 91-------------------------------------------------------------------------------
Dsrc/rnfl_c.h | 35-----------------------------------
Dsrc/rnfl_log.c | 129-------------------------------------------------------------------------------
Dsrc/rnfl_log.h | 73-------------------------------------------------------------------------
Asrc/rnsl.c | 314+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/rnsl.h | 100+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/rnsl_c.h | 38++++++++++++++++++++++++++++++++++++++
Asrc/rnsl_log.c | 129+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/rnsl_log.h | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/test_rnfl.c | 76----------------------------------------------------------------------------
Asrc/test_rnsl.c | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
14 files changed, 760 insertions(+), 544 deletions(-)

diff --git a/README.md b/README.md @@ -1,6 +1,6 @@ -# Rad-Net File List +# Rad-Net String List -This C library loads a set of file names listed according to the rnml file format +This C library loads a set of file names listed according to the rnsl file format ## How to build @@ -30,6 +30,6 @@ Copyright (C) 2022 Université Paul Sabatier (<contact@laplace.univ-tlse.fr>) ## License -Rad-Net File List is free software released under the GPL v3+ license: GNU GPL +Rad-Net String List is free software released under the GPL v3+ license: GNU GPL version 3 or later. You are welcome to redistribute it under certain conditions; refer to the COPYING file for details. diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -19,10 +19,10 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. cmake_minimum_required(VERSION 3.1) -project(rnfl C) +project(rnsl C) enable_testing() -set(RNFL_SOURCE_DIR ${PROJECT_SOURCE_DIR}/../src) +set(RNSL_SOURCE_DIR ${PROJECT_SOURCE_DIR}/../src) option(NO_TEST "Do not build tests" OFF) ################################################################################ @@ -45,44 +45,44 @@ set(VERSION_MINOR 0) set(VERSION_PATCH 0) set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) -set(RNFL_FILES_SRC - rnfl.c - rnfl_log.c) -set(RNFL_FILES_INC - rnfl_c.h - rnfl_log.h) -set(RNFL_FILES_INC_API - rnfl.h) +set(RNSL_FILES_SRC + rnsl.c + rnsl_log.c) +set(RNSL_FILES_INC + rnsl_c.h + rnsl_log.h) +set(RNSL_FILES_INC_API + rnsl.h) -set(RNFL_FILES_DOC COPYING README.md) +set(RNSL_FILES_DOC COPYING README.md) -# Prepend each file in the `RNFL_FILES_<SRC|INC>' list by `RNFL_SOURCE_DIR' -rcmake_prepend_path(RNFL_FILES_SRC ${RNFL_SOURCE_DIR}) -rcmake_prepend_path(RNFL_FILES_INC ${RNFL_SOURCE_DIR}) -rcmake_prepend_path(RNFL_FILES_INC_API ${RNFL_SOURCE_DIR}) -rcmake_prepend_path(RNFL_FILES_DOC ${PROJECT_SOURCE_DIR}/../) +# Prepend each file in the `RNSL_FILES_<SRC|INC>' list by `RNSL_SOURCE_DIR' +rcmake_prepend_path(RNSL_FILES_SRC ${RNSL_SOURCE_DIR}) +rcmake_prepend_path(RNSL_FILES_INC ${RNSL_SOURCE_DIR}) +rcmake_prepend_path(RNSL_FILES_INC_API ${RNSL_SOURCE_DIR}) +rcmake_prepend_path(RNSL_FILES_DOC ${PROJECT_SOURCE_DIR}/../) -add_library(rnfl SHARED ${RNFL_FILES_SRC} ${RNFL_FILES_INC} ${RNFL_FILES_INC_API}) -target_link_libraries(rnfl RSys) +add_library(rnsl SHARED ${RNSL_FILES_SRC} ${RNSL_FILES_INC} ${RNSL_FILES_INC_API}) +target_link_libraries(rnsl RSys) if(CMAKE_COMPILER_IS_GNUCC) - target_link_libraries(rnfl m) + target_link_libraries(rnsl m) endif() -set_target_properties(rnfl PROPERTIES - DEFINE_SYMBOL RNFL_SHARED_BUILD +set_target_properties(rnsl PROPERTIES + DEFINE_SYMBOL RNSL_SHARED_BUILD VERSION ${VERSION} SOVERSION ${VERSION_MAJOR}) -rcmake_setup_devel(rnfl StarCK ${VERSION} rad-net/rnfl_version.h) +rcmake_setup_devel(rnsl StarCK ${VERSION} rad-net/rnsl_version.h) ################################################################################ # Add tests ################################################################################ if(NOT NO_TEST) function(new_test _name) - add_executable(${_name} ${RNFL_SOURCE_DIR}/${_name}.c) - target_link_libraries(${_name} rnfl RSys ${ARGN}) + add_executable(${_name} ${RNSL_SOURCE_DIR}/${_name}.c) + target_link_libraries(${_name} rnsl RSys ${ARGN}) add_test(${_name} ${_name}) endfunction() @@ -114,9 +114,9 @@ endif() ################################################################################ # Define output & install directories ################################################################################ -install(TARGETS rnfl +install(TARGETS rnsl ARCHIVE DESTINATION bin LIBRARY DESTINATION lib RUNTIME DESTINATION bin) -install(FILES ${RNFL_FILES_INC_API} DESTINATION include/rad-net) -install(FILES ${RNFL_FILES_DOC} DESTINATION share/doc/rnfl) +install(FILES ${RNSL_FILES_INC_API} DESTINATION include/rad-net) +install(FILES ${RNSL_FILES_DOC} DESTINATION share/doc/rnsl) diff --git a/src/rnfl.c b/src/rnfl.c @@ -1,110 +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/>. */ - -#include "rnfl.h" -#include "rnfl_c.h" -#include "rnfl_log.h" - -/******************************************************************************* - * Helper functions - ******************************************************************************/ -static INLINE res_T -check_rnfl_create_args(const struct rnfl_create_args* args) -{ - /* Nothing to check. Only return RES_BAD_ARG if args is NULL */ - return args ? RES_OK : RES_BAD_ARG; -} - -static void -release_rnfl(ref_T* ref) -{ - struct rnfl* rnfl; - ASSERT(ref); - rnfl = CONTAINER_OF(ref, struct rnfl, ref); - if(rnfl->logger == &rnfl->logger__) logger_release(&rnfl->logger__); - MEM_RM(rnfl->allocator, rnfl); -} - -/******************************************************************************* - * Exported functions - ******************************************************************************/ -res_T -rnfl_create - (const struct rnfl_create_args* args, - struct rnfl** out_rnfl) -{ - struct rnfl* rnfl = NULL; - struct mem_allocator* allocator = NULL; - res_T res = RES_OK; - - if(!out_rnfl) { res = RES_BAD_ARG; goto error; } - res = check_rnfl_create_args(args); - if(res != RES_OK) goto error; - - allocator = args->allocator ? args->allocator : &mem_default_allocator; - rnfl = MEM_CALLOC(allocator, 1, sizeof(*rnfl)); - if(!rnfl) { - if(args->verbose) { - #define ERR_STR "Could not allocate the Rad-Net File List device.\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(&rnfl->ref); - rnfl->allocator = allocator; - rnfl->verbose = args->verbose; - if(args->logger) { - rnfl->logger = args->logger; - } else { - setup_log_default(rnfl); - } - -exit: - if(out_rnfl) *out_rnfl = rnfl; - return res; -error: - if(rnfl) { - RNFL(ref_put(rnfl)); - rnfl = NULL; - } - goto exit; -} - -res_T -rnfl_ref_get(struct rnfl* rnfl) -{ - if(!rnfl) return RES_BAD_ARG; - ref_get(&rnfl->ref); - return RES_OK; -} - -res_T -rnfl_ref_put(struct rnfl* rnfl) -{ - if(!rnfl) return RES_BAD_ARG; - ref_put(&rnfl->ref, release_rnfl); - return RES_OK; -} diff --git a/src/rnfl.h b/src/rnfl.h @@ -1,91 +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/>. */ - -#ifndef RNFL_H -#define RNFL_H - -#include <rsys/rsys.h> - -/* Library symbol management */ -#if defined(RNFL_SHARED_BUILD) /* Build shared library */ - #define RNFL_API extern EXPORT_SYM -#elif defined(RNFL_STATIC) /* Use/build static library */ - #define RNFL_API extern LOCAL_SYM -#else /* Use shared library */ - #define RNFL_API extern IMPORT_SYM -#endif - -/* Helper macro that asserts if the invocation of the rnfl function `Func' - * returns an error. One should use this macro on suvm function calls for - * which no explicit error checking is performed */ -#ifndef NDEBUG - #define RNFL(Func) ASSERT(rnfl_ ## Func == RES_OK) -#else - #define RNFL(Func) rnfl_ ## Func -#endif - -struct rnfl_create_args { - struct logger* logger; /* May be NULL <=> default logger */ - struct mem_allocator* allocator; /* NULL <=> use default allocator */ - int verbose; /* Verbosity level */ -}; -#define RNFL_CREATE_ARGS_DEFAULT__ {NULL, NULL, 0} -static const struct rnfl_create_args RNFL_CREATE_ARGS_DEFAULT = - RNFL_CREATE_ARGS_DEFAULT__; - -/* Forward declaration of external data types */ -struct logger; -struct mem_allocator; - -/* Forward declaration of opaque data types */ -struct rnfl; - -BEGIN_DECLS - -/******************************************************************************* - * API of the Rad-Net file list - ******************************************************************************/ -RNFL_API res_T -rnfl_create - (const struct rnfl_create_args* args, - struct rnfl** rnfl); - -RNFL_API res_T -rnfl_ref_get - (struct rnfl* rnfl); - -RNFL_API res_T -rnfl_ref_put - (struct rnfl* rnfl); - -RNFL_API res_T -rnfl_load - (struct rnfl* rnfl, - const char* filename); - -RNFL_API res_T -rnfl_load_stream - (struct rnfl* rnfl, - FILE* stream, - const char* stream_name); - -END_DECLS - -#endif /* RNFL_H */ diff --git a/src/rnfl_c.h b/src/rnfl_c.h @@ -1,35 +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/>. */ - -#ifndef RNFL_C_H -#define RNFL_C_H - -#include <rsys/logger.h> -#include <rsys/ref_count.h> - -struct rnfl { - struct mem_allocator* allocator; - struct logger* logger; - struct logger logger__; - int verbose; /* Verbosity level */ - ref_T ref; -}; - -#endif /* RNFL_C_H */ diff --git a/src/rnfl_log.c b/src/rnfl_log.c @@ -1,129 +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/>. */ - -#include "rnfl_c.h" -#include "rnfl_log.h" - -#include <rsys/cstr.h> -#include <rsys/logger.h> - -#include <stdarg.h> - -/******************************************************************************* - * Helper functions - ******************************************************************************/ -static INLINE void -log_msg - (const struct rnfl* fl, - const enum log_type stream, - const char* msg, - va_list vargs) -{ - ASSERT(fl && msg); - if(fl->verbose) { - res_T res; (void)res; - res = logger_vprint(fl->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 rnfl* fl) -{ - res_T res = RES_OK; - ASSERT(fl); - - res = logger_init(fl->allocator, &fl->logger__); - if(res != RES_OK) { - if(fl->verbose) { - fprintf(stderr, - MSG_ERROR_PREFIX - "Could not setup the default logger -- %s.\n", - res_to_cstr(res)); - } - goto error; - } - logger_set_stream(&fl->logger__, LOG_OUTPUT, print_info, NULL); - logger_set_stream(&fl->logger__, LOG_ERROR, print_err, NULL); - logger_set_stream(&fl->logger__, LOG_WARNING, print_warn, NULL); - fl->logger = &fl->logger__; - -exit: - return res; -error: - goto exit; -} - -void -log_info(const struct rnfl* fl, const char* msg, ...) -{ - va_list vargs_list; - ASSERT(fl && msg); - - va_start(vargs_list, msg); - log_msg(fl, LOG_OUTPUT, msg, vargs_list); - va_end(vargs_list); -} - -void -log_err(const struct rnfl* fl, const char* msg, ...) -{ - va_list vargs_list; - ASSERT(fl && msg); - - va_start(vargs_list, msg); - log_msg(fl, LOG_ERROR, msg, vargs_list); - va_end(vargs_list); -} - -void -log_warn(const struct rnfl* fl, const char* msg, ...) -{ - va_list vargs_list; - ASSERT(fl && msg); - - va_start(vargs_list, msg); - log_msg(fl, LOG_WARNING, msg, vargs_list); - va_end(vargs_list); -} diff --git a/src/rnfl_log.h b/src/rnfl_log.h @@ -1,73 +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/>. */ - -#ifndef RNFL_LOG_H -#define RNFL_LOG_H - -#include <rsys/rsys.h> - -#define MSG_INFO_PREFIX "RNFL:\x1b[1m\x1b[32minfo\x1b[0m: " -#define MSG_ERROR_PREFIX "RNFL:\x1b[1m\x1b[31merror\x1b[0m: " -#define MSG_WARNING_PREFIX "RNFL:\x1b[1m\x1b[33mwarning\x1b[0m: " - -struct rnfl; -struct logger; - -extern LOCAL_SYM res_T -setup_log_default - (struct rnfl* rnfl); - -/* Conditionally log a message on the LOG_OUTPUT stream of the rnfl logger, - * with respect to its verbose flag */ -extern LOCAL_SYM void -log_info - (const struct rnfl* rnfl, - const char* msg, - ...) -#ifdef COMPILER_GCC - __attribute((format(printf, 2, 3))) -#endif -; - -/* Conditionally log a message on the LOG_ERROR stream of the rnfl logger, - * with respect to its verbose flag */ -extern LOCAL_SYM void -log_err - (const struct rnfl* rnfl, - const char* msg, - ...) -#ifdef COMPILER_GCC - __attribute((format(printf, 2, 3))) -#endif -; - -/* Conditionally log a message on the LOG_WARNING stream of the rnfl logger, - * with respect to its verbose flag */ -extern LOCAL_SYM void -log_warn - (const struct rnfl* rnfl, - const char* msg, - ...) -#ifdef COMPILER_GCC - __attribute((format(printf, 2, 3))) -#endif -; - -#endif /* RNFL_LOG_H */ diff --git a/src/rnsl.c b/src/rnsl.c @@ -0,0 +1,314 @@ +/* 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 "rnsl.h" +#include "rnsl_c.h" +#include "rnsl_log.h" + +#include <rsys/cstr.h> +#include <rsys/text_reader.h> + +#include <string.h> +#include <wordexp.h> + +/******************************************************************************* + * Helper functions + ******************************************************************************/ +static res_T +parse_string(struct rnsl* rnsl, struct txtrdr* txtrdr, struct str* str) +{ + wordexp_t wexp; + char* tk = NULL; + char* tk_ctx = NULL; + int wexp_is_allocated = 1; + res_T res = RES_OK; + int err = 0; + ASSERT(rnsl && txtrdr && str); + + res = txtrdr_read_line(txtrdr); + if(res != RES_OK) { + log_err(rnsl, "%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_str_size_get(&rnsl->strings); + const size_t nparsed = (size_t)(str - darray_str_cdata_get(&rnsl->strings)); + log_err(rnsl, + "%s:%lu: missing a string. " + "Expecting %lu string%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(rnsl, "%s:%lu: unable to expand string\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); + + if(wexp.we_wordc > 1) { + log_warn(rnsl, + "%s:%lu: multiple strings on the same line. " + "Only the first one will be loaded\n", + txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr)); + } + + res = str_set(str, wexp.we_wordv[0]); + if(res != RES_OK) { + log_err(rnsl, "%s:%lu: unable to store the parsed string `%s' -- %s\n", + txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr), + wexp.we_wordv[0], res_to_cstr(res)); + goto error; + } + +exit: + if(wexp_is_allocated) wordfree(&wexp); + return res; +error: + goto exit; +} + + +static res_T +load_stream(struct rnsl* rnsl, FILE* file, const char* path) +{ + struct txtrdr* txtrdr = NULL; + char* tk = NULL; + char* tk_ctx = NULL; + size_t istr = 0; + unsigned long nstrs = 0; + res_T res = RES_OK; + ASSERT(rnsl && file && path); + + darray_str_clear(&rnsl->strings); /* Clean up */ + + res = txtrdr_stream(rnsl->allocator, file, path, '#', &txtrdr); + if(res != RES_OK) { + log_err(rnsl, "could not create text reader to parse file `%s' -- %s\n", + path, res_to_cstr(res)); + goto error; + } + + res = txtrdr_read_line(txtrdr); + if(res != RES_OK) { + log_err(rnsl, "%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(rnsl, "%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, &nstrs); + if(res == RES_OK && nstrs == 0) res = RES_BAD_ARG; + if(res != RES_OK) { + log_err(rnsl, "%s:%lu: invalid number of string %lu\n", + txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr), + nstrs); + goto error; + } + + res = darray_str_resize(&rnsl->strings, nstrs); + if(res != RES_OK) { + log_err(rnsl, "%s: could not allocate the list of %lu strings -- %s\n", + txtrdr_get_name(txtrdr), nstrs, res_to_cstr(res)); + goto error; + } + + tk = strtok_r(NULL, " \t", &tk_ctx); + if(tk) { + log_warn(rnsl, "%s:%lu: unexpected text `%s'\n", + txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr), tk); + } + + FOR_EACH(istr, 0, nstrs) { + struct str* str = darray_str_data_get(&rnsl->strings)+istr; + res = parse_string(rnsl, txtrdr, str); + if(res != RES_OK) goto error; + } + +exit: + if(txtrdr) txtrdr_ref_put(txtrdr); + return res; +error: + darray_str_clear(&rnsl->strings); + goto exit; +} + + +static INLINE res_T +check_rnsl_create_args(const struct rnsl_create_args* args) +{ + /* Nothing to check. Only return RES_BAD_ARG if args is NULL */ + return args ? RES_OK : RES_BAD_ARG; +} + +static void +release_rnsl(ref_T* ref) +{ + struct rnsl* rnsl; + ASSERT(ref); + rnsl = CONTAINER_OF(ref, struct rnsl, ref); + if(rnsl->logger == &rnsl->logger__) logger_release(&rnsl->logger__); + darray_str_release(&rnsl->strings); + MEM_RM(rnsl->allocator, rnsl); +} + +/******************************************************************************* + * Exported functions + ******************************************************************************/ +res_T +rnsl_create + (const struct rnsl_create_args* args, + struct rnsl** out_rnsl) +{ + struct rnsl* rnsl = NULL; + struct mem_allocator* allocator = NULL; + res_T res = RES_OK; + + if(!out_rnsl) { res = RES_BAD_ARG; goto error; } + res = check_rnsl_create_args(args); + if(res != RES_OK) goto error; + + allocator = args->allocator ? args->allocator : &mem_default_allocator; + rnsl = MEM_CALLOC(allocator, 1, sizeof(*rnsl)); + if(!rnsl) { + if(args->verbose) { + #define ERR_STR "Could not allocate the Rad-Net String List device.\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(&rnsl->ref); + rnsl->allocator = allocator; + rnsl->verbose = args->verbose; + darray_str_init(rnsl->allocator, &rnsl->strings); + if(args->logger) { + rnsl->logger = args->logger; + } else { + setup_log_default(rnsl); + } + +exit: + if(out_rnsl) *out_rnsl = rnsl; + return res; +error: + if(rnsl) { + RNSL(ref_put(rnsl)); + rnsl = NULL; + } + goto exit; +} + +res_T +rnsl_ref_get(struct rnsl* rnsl) +{ + if(!rnsl) return RES_BAD_ARG; + ref_get(&rnsl->ref); + return RES_OK; +} + +res_T +rnsl_ref_put(struct rnsl* rnsl) +{ + if(!rnsl) return RES_BAD_ARG; + ref_put(&rnsl->ref, release_rnsl); + return RES_OK; +} + +res_T +rnsl_load(struct rnsl* rnsl, const char* path) +{ + FILE* file = NULL; + res_T res = RES_OK; + + if(!rnsl || !path) { + res = RES_BAD_ARG; + goto error; + } + + file = fopen(path, "r"); + if(!file) { + log_err(rnsl, "%s: error opening file `%s'.\n", FUNC_NAME, path); + res = RES_IO_ERR; + goto error; + } + + res = load_stream(rnsl, file, path); + if(res != RES_OK) goto error; + +exit: + if(file) fclose(file); + return res; +error: + goto exit; +} + +res_T +rnsl_load_stream + (struct rnsl* rnsl, + FILE* stream, + const char* stream_name) +{ + if(!rnsl || !stream) return RES_BAD_ARG; + return load_stream(rnsl, stream, stream_name ? stream_name : "<stream>"); +} + +size_t +rnsl_get_strings_count(const struct rnsl* rnsl) +{ + ASSERT(rnsl); + return darray_str_size_get(&rnsl->strings); +} + +const char* +rnsl_get_string(const struct rnsl* rnsl, const size_t istring) +{ + ASSERT(rnsl && istring < rnsl_get_strings_count(rnsl)); + return str_cget(darray_str_cdata_get(&rnsl->strings)+istring); +} diff --git a/src/rnsl.h b/src/rnsl.h @@ -0,0 +1,100 @@ +/* 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/>. */ + +#ifndef RNSL_H +#define RNSL_H + +#include <rsys/rsys.h> + +/* Library symbol management */ +#if defined(RNSL_SHARED_BUILD) /* Build shared library */ + #define RNSL_API extern EXPORT_SYM +#elif defined(RNSL_STATIC) /* Use/build static library */ + #define RNSL_API extern LOCAL_SYM +#else /* Use shared library */ + #define RNSL_API extern IMPORT_SYM +#endif + +/* Helper macro that asserts if the invocation of the rnsl function `Func' + * returns an error. One should use this macro on suvm function calls for + * which no explicit error checking is performed */ +#ifndef NDEBUG + #define RNSL(Func) ASSERT(rnsl_ ## Func == RES_OK) +#else + #define RNSL(Func) rnsl_ ## Func +#endif + +struct rnsl_create_args { + struct logger* logger; /* May be NULL <=> default logger */ + struct mem_allocator* allocator; /* NULL <=> use default allocator */ + int verbose; /* Verbosity level */ +}; +#define RNSL_CREATE_ARGS_DEFAULT__ {NULL, NULL, 0} +static const struct rnsl_create_args RNSL_CREATE_ARGS_DEFAULT = + RNSL_CREATE_ARGS_DEFAULT__; + +/* Forward declaration of external data types */ +struct logger; +struct mem_allocator; + +/* Forward declaration of opaque data types */ +struct rnsl; + +BEGIN_DECLS + +/******************************************************************************* + * API of the Rad-Net file list + ******************************************************************************/ +RNSL_API res_T +rnsl_create + (const struct rnsl_create_args* args, + struct rnsl** rnsl); + +RNSL_API res_T +rnsl_ref_get + (struct rnsl* rnsl); + +RNSL_API res_T +rnsl_ref_put + (struct rnsl* rnsl); + +RNSL_API res_T +rnsl_load + (struct rnsl* rnsl, + const char* filename); + +RNSL_API res_T +rnsl_load_stream + (struct rnsl* rnsl, + FILE* stream, + const char* stream_name); + +RNSL_API size_t +rnsl_get_strings_count + (const struct rnsl* rnsl); + +RNSL_API const char* +rnsl_get_string + (const struct rnsl* rnsl, + const size_t istring); + +END_DECLS + +#endif /* RNSL_H */ diff --git a/src/rnsl_c.h b/src/rnsl_c.h @@ -0,0 +1,38 @@ +/* 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/>. */ + +#ifndef RNSL_C_H +#define RNSL_C_H + +#include <rsys/dynamic_array_str.h> +#include <rsys/logger.h> +#include <rsys/ref_count.h> + +struct rnsl { + struct darray_str strings; + + struct mem_allocator* allocator; + struct logger* logger; + struct logger logger__; + int verbose; /* Verbosity level */ + ref_T ref; +}; + +#endif /* RNSL_C_H */ diff --git a/src/rnsl_log.c b/src/rnsl_log.c @@ -0,0 +1,129 @@ +/* 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/>. */ + +#include "rnsl_c.h" +#include "rnsl_log.h" + +#include <rsys/cstr.h> +#include <rsys/logger.h> + +#include <stdarg.h> + +/******************************************************************************* + * Helper functions + ******************************************************************************/ +static INLINE void +log_msg + (const struct rnsl* rnsl, + const enum log_type stream, + const char* msg, + va_list vargs) +{ + ASSERT(rnsl && msg); + if(rnsl->verbose) { + res_T res; (void)res; + res = logger_vprint(rnsl->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 rnsl* rnsl) +{ + res_T res = RES_OK; + ASSERT(rnsl); + + res = logger_init(rnsl->allocator, &rnsl->logger__); + if(res != RES_OK) { + if(rnsl->verbose) { + fprintf(stderr, + MSG_ERROR_PREFIX + "Could not setup the default logger -- %s.\n", + res_to_cstr(res)); + } + goto error; + } + logger_set_stream(&rnsl->logger__, LOG_OUTPUT, print_info, NULL); + logger_set_stream(&rnsl->logger__, LOG_ERROR, print_err, NULL); + logger_set_stream(&rnsl->logger__, LOG_WARNING, print_warn, NULL); + rnsl->logger = &rnsl->logger__; + +exit: + return res; +error: + goto exit; +} + +void +log_info(const struct rnsl* rnsl, const char* msg, ...) +{ + va_list vargs_list; + ASSERT(rnsl && msg); + + va_start(vargs_list, msg); + log_msg(rnsl, LOG_OUTPUT, msg, vargs_list); + va_end(vargs_list); +} + +void +log_err(const struct rnsl* rnsl, const char* msg, ...) +{ + va_list vargs_list; + ASSERT(rnsl && msg); + + va_start(vargs_list, msg); + log_msg(rnsl, LOG_ERROR, msg, vargs_list); + va_end(vargs_list); +} + +void +log_warn(const struct rnsl* rnsl, const char* msg, ...) +{ + va_list vargs_list; + ASSERT(rnsl && msg); + + va_start(vargs_list, msg); + log_msg(rnsl, LOG_WARNING, msg, vargs_list); + va_end(vargs_list); +} diff --git a/src/rnsl_log.h b/src/rnsl_log.h @@ -0,0 +1,73 @@ +/* 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/>. */ + +#ifndef RNSL_LOG_H +#define RNSL_LOG_H + +#include <rsys/rsys.h> + +#define MSG_INFO_PREFIX "RNSL:\x1b[1m\x1b[32minfo\x1b[0m: " +#define MSG_ERROR_PREFIX "RNSL:\x1b[1m\x1b[31merror\x1b[0m: " +#define MSG_WARNING_PREFIX "RNSL:\x1b[1m\x1b[33mwarning\x1b[0m: " + +struct rnsl; +struct logger; + +extern LOCAL_SYM res_T +setup_log_default + (struct rnsl* rnsl); + +/* Conditionally log a message on the LOG_OUTPUT stream of the rnsl logger, + * with respect to its verbose flag */ +extern LOCAL_SYM void +log_info + (const struct rnsl* rnsl, + const char* msg, + ...) +#ifdef COMPILER_GCC + __attribute((format(printf, 2, 3))) +#endif +; + +/* Conditionally log a message on the LOG_ERROR stream of the rnsl logger, + * with respect to its verbose flag */ +extern LOCAL_SYM void +log_err + (const struct rnsl* rnsl, + const char* msg, + ...) +#ifdef COMPILER_GCC + __attribute((format(printf, 2, 3))) +#endif +; + +/* Conditionally log a message on the LOG_WARNING stream of the rnsl logger, + * with respect to its verbose flag */ +extern LOCAL_SYM void +log_warn + (const struct rnsl* rnsl, + const char* msg, + ...) +#ifdef COMPILER_GCC + __attribute((format(printf, 2, 3))) +#endif +; + +#endif /* RNSL_LOG_H */ diff --git a/src/test_rnfl.c b/src/test_rnfl.c @@ -1,76 +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/>. */ - -#include "rnfl.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 rnfl_create_args args = RNFL_CREATE_ARGS_DEFAULT; - struct rnfl* rnfl; - (void)argc, (void)argv; - - CHK(rnfl_create(NULL, &rnfl) == RES_BAD_ARG); - CHK(rnfl_create(&args, NULL) == RES_BAD_ARG); - CHK(rnfl_create(&args, &rnfl) == RES_OK); - - CHK(rnfl_ref_get(NULL) == RES_BAD_ARG); - CHK(rnfl_ref_get(rnfl) == RES_OK); - CHK(rnfl_ref_put(NULL) == RES_BAD_ARG); - CHK(rnfl_ref_put(rnfl) == RES_OK); - CHK(rnfl_ref_put(rnfl) == RES_OK); - - CHK(mem_init_proxy_allocator(&allocator, &mem_default_allocator) == RES_OK); - args.allocator = &allocator; - args.verbose = 1; - CHK(rnfl_create(&args, &rnfl) == RES_OK); - CHK(rnfl_ref_put(rnfl) == 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; - args.verbose = 0; - CHK(rnfl_create(&args, &rnfl) == RES_OK); - CHK(rnfl_ref_put(rnfl) == RES_OK); - args.allocator = NULL; - CHK(rnfl_create(&args, &rnfl) == RES_OK); - CHK(rnfl_ref_put(rnfl) == RES_OK); - - logger_release(&logger); - mem_shutdown_proxy_allocator(&allocator); - CHK(mem_allocated_size() == 0); - return 0; -} - diff --git a/src/test_rnsl.c b/src/test_rnsl.c @@ -0,0 +1,76 @@ +/* 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/>. */ + +#include "rnsl.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 rnsl_create_args args = RNSL_CREATE_ARGS_DEFAULT; + struct rnsl* rnsl; + (void)argc, (void)argv; + + CHK(rnsl_create(NULL, &rnsl) == RES_BAD_ARG); + CHK(rnsl_create(&args, NULL) == RES_BAD_ARG); + CHK(rnsl_create(&args, &rnsl) == RES_OK); + + CHK(rnsl_ref_get(NULL) == RES_BAD_ARG); + CHK(rnsl_ref_get(rnsl) == RES_OK); + CHK(rnsl_ref_put(NULL) == RES_BAD_ARG); + CHK(rnsl_ref_put(rnsl) == RES_OK); + CHK(rnsl_ref_put(rnsl) == RES_OK); + + CHK(mem_init_proxy_allocator(&allocator, &mem_default_allocator) == RES_OK); + args.allocator = &allocator; + args.verbose = 1; + CHK(rnsl_create(&args, &rnsl) == RES_OK); + CHK(rnsl_ref_put(rnsl) == 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; + args.verbose = 0; + CHK(rnsl_create(&args, &rnsl) == RES_OK); + CHK(rnsl_ref_put(rnsl) == RES_OK); + args.allocator = NULL; + CHK(rnsl_create(&args, &rnsl) == RES_OK); + CHK(rnsl_ref_put(rnsl) == RES_OK); + + logger_release(&logger); + mem_shutdown_proxy_allocator(&allocator); + CHK(mem_allocated_size() == 0); + return 0; +} +