solstice

Compute collected power and efficiencies of a solar plant
git clone git://git.meso-star.com/solstice.git
Log | Files | Refs | README | LICENSE

commit a5d0b804bd05a397c1b8ca9c19f89ed4d8cc0f36
parent 8ddb17fd4d6d721cb8733c3846391a91b4bb6765
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Mon, 16 Jan 2017 10:14:24 +0100

Rename the solreceivers library

Rename in srcvl, i.e. Solstice ReCeiVers Loader.

Diffstat:
Mcmake/receivers/CMakeLists.txt | 36++++++++++++++++++------------------
Dsrc/receivers/solreceivers.c | 431-------------------------------------------------------------------------------
Dsrc/receivers/solreceivers.h | 73-------------------------------------------------------------------------
Asrc/receivers/srcvl.c | 431+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/receivers/srcvl.h | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/receivers/test_solreceivers.c | 80-------------------------------------------------------------------------------
Dsrc/receivers/test_solreceivers2.c | 94-------------------------------------------------------------------------------
Asrc/receivers/test_srcvl.c | 80+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/receivers/test_srcvl2.c | 94+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9 files changed, 696 insertions(+), 696 deletions(-)

diff --git a/cmake/receivers/CMakeLists.txt b/cmake/receivers/CMakeLists.txt @@ -14,9 +14,9 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. cmake_minimum_required(VERSION 2.8) -project(solstice-receivers C) +project(srcvl C) -set(SOLRECEIVERS_SOURCE_DIR ${PROJECT_SOURCE_DIR}/../../src/receivers) +set(SRCVL_SOURCE_DIR ${PROJECT_SOURCE_DIR}/../../src/receivers) ################################################################################ # Define include directories @@ -24,23 +24,23 @@ set(SOLRECEIVERS_SOURCE_DIR ${PROJECT_SOURCE_DIR}/../../src/receivers) include_directories( ${LibYAML_INCLUDE_DIR} ${RSys_INCLUDE_DIR} - ${SOLRECEIVERS_SOURCE_DIR}/../) + ${SRCVL_SOURCE_DIR}/../) ################################################################################ # Configure and define targets ################################################################################ -set(SOLRECEIVERS_FILES_SRC solreceivers.c) -set(SOLRECEIVERS_FILES_INC solreceivers.h) +set(SRCVL_FILES_SRC srcvl.c) +set(SRCVL_FILES_INC srcvl.h) -rcmake_prepend_path(SOLRECEIVERS_FILES_SRC ${SOLRECEIVERS_SOURCE_DIR}) -rcmake_prepend_path(SOLRECEIVERS_FILES_INC ${SOLRECEIVERS_SOURCE_DIR}) +rcmake_prepend_path(SRCVL_FILES_SRC ${SRCVL_SOURCE_DIR}) +rcmake_prepend_path(SRCVL_FILES_INC ${SRCVL_SOURCE_DIR}) if(CMAKE_COMPILER_IS_GNUCC) set(MATH_LIB m) endif() -add_library(solreceivers STATIC ${SOLRECEIVERS_FILES_SRC} ${SOLRECEIVERS_FILES_INC}) -target_link_libraries(solreceivers LibYAML ${MATH_LIB}) +add_library(srcvl STATIC ${SRCVL_FILES_SRC} ${SRCVL_FILES_INC}) +target_link_libraries(srcvl LibYAML ${MATH_LIB}) ################################################################################ # Tests @@ -48,9 +48,9 @@ target_link_libraries(solreceivers LibYAML ${MATH_LIB}) if(NOT NO_TEST) function(build_test _name) add_executable(${_name} - ${SOLRECEIVERS_SOURCE_DIR}/${_name}.c - ${SOLRECEIVERS_SOURCE_DIR}/../test_solstice_utils.h) - target_link_libraries(${_name} LibYAML ${MATH_LIB} RSys solreceivers) + ${SRCVL_SOURCE_DIR}/${_name}.c + ${SRCVL_SOURCE_DIR}/../test_solstice_utils.h) + target_link_libraries(${_name} LibYAML ${MATH_LIB} RSys srcvl) endfunction() function(new_test _name) @@ -58,13 +58,13 @@ if(NOT NO_TEST) add_test(${_name} ${_name}) endfunction() - build_test(test_solreceivers) - add_test(test_solreceivers_ok test_solreceivers - ${SOLRECEIVERS_SOURCE_DIR}/yaml/test_ok.yaml) - add_test(test_solreceivers_ko test_solreceivers -e - ${SOLRECEIVERS_SOURCE_DIR}/yaml/test_ko.yaml) + build_test(test_srcvl) + add_test(test_srcvl_ok test_srcvl + ${SRCVL_SOURCE_DIR}/yaml/test_ok.yaml) + add_test(test_srvvl_ko test_srcvl -e + ${SRCVL_SOURCE_DIR}/yaml/test_ko.yaml) - new_test(test_solreceivers2) + new_test(test_srcvl2) endif() diff --git a/src/receivers/solreceivers.c b/src/receivers/solreceivers.c @@ -1,431 +0,0 @@ -/* Copyright (C) CNRS 2016-2017 - * - * 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 "solreceivers.h" - -#include <rsys/dynamic_array.h> -#include <rsys/mem_allocator.h> -#include <rsys/ref_count.h> -#include <rsys/str.h> - -#include <stdio.h> -#include <stdarg.h> -#include <yaml.h> - -struct receiver { - struct str name; - enum solreceiver_side side; -}; - -static INLINE void -receiver_init(struct mem_allocator* allocator, struct receiver* receiver) -{ - ASSERT(receiver); - str_init(allocator, &receiver->name); - receiver->side = SOLRECEIVER_FRONT_AND_BACK; -} - -static INLINE void -receiver_release(struct receiver* receiver) -{ - ASSERT(receiver); - str_release(&receiver->name); -} - -static INLINE res_T -receiver_copy(struct receiver* dst, const struct receiver* src) -{ - ASSERT(dst && src); - dst->side = src->side; - return str_copy(&dst->name, &src->name); -} - - -static INLINE res_T -receiver_copy_and_release(struct receiver* dst, struct receiver* src) -{ - ASSERT(dst && src); - dst->side = src->side; - return str_copy_and_release(&dst->name, &src->name); -} - -#define DARRAY_NAME receiver -#define DARRAY_DATA struct receiver -#define DARRAY_FUNCTOR_INIT receiver_init -#define DARRAY_FUNCTOR_RELEASE receiver_release -#define DARRAY_FUNCTOR_COPY receiver_copy -#define DARRAY_FUNCTOR_COPY_AND_RELEASE receiver_copy_and_release -#include <rsys/dynamic_array.h> - -struct solreceivers { - yaml_parser_t parser; - int parser_is_init; - struct darray_receiver receivers; - - struct str stream_name; - - ref_T ref; - struct mem_allocator* allocator; -}; - -/******************************************************************************* - * Helper functions - ******************************************************************************/ -static INLINE void -log_err - (const struct solreceivers* receivers, - const yaml_node_t* node, - const char* fmt, - ...) -{ - va_list vargs_list; - ASSERT(receivers && node && fmt); - - fprintf(stderr, "%s:%lu:%lu: ", - str_cget(&receivers->stream_name), - (unsigned long)node->start_mark.line+1, - (unsigned long)node->start_mark.column+1); - va_start(vargs_list, fmt); - vfprintf(stderr, fmt, vargs_list); - va_end(vargs_list); -} - -static res_T -parse_string - (struct solreceivers* receivers, - yaml_node_t* string, - struct str* str) -{ - res_T res = RES_OK; - ASSERT(string && str); - - if(string->type != YAML_SCALAR_NODE - || !strlen((char*)string->data.scalar.value)) { - log_err(receivers, string, "expect a character string.\n"); - res = RES_BAD_ARG; - goto error; - } - res = str_set(str, (char*)string->data.scalar.value); - if(res != RES_OK) { - log_err(receivers, string, "could not register the string `%s'.\n", - string->data.scalar.value); - goto error; - } - -exit: - return res; -error: - goto exit; -} - -static res_T -parse_side - (struct solreceivers* receivers, - yaml_node_t* side, - enum solreceiver_side* out_side) -{ - res_T res = RES_OK; - ASSERT(side && out_side); - - if(side->type != YAML_SCALAR_NODE) { - log_err(receivers, side, "expect a character string.\n"); - res = RES_BAD_ARG; - goto error; - } - - if(!strcmp((char*)side->data.scalar.value, "FRONT")) { - *out_side = SOLRECEIVER_FRONT; - } else if(!strcmp((char*)side->data.scalar.value, "BACK")) { - *out_side = SOLRECEIVER_BACK; - } else if(!strcmp((char*)side->data.scalar.value, "FRONT_AND_BACK")) { - *out_side = SOLRECEIVER_FRONT_AND_BACK; - } else { - log_err(receivers, side, "unknown side valie `%s'.\n", - side->data.scalar.value); - res = RES_BAD_ARG; - goto error; - } -exit: - return res; -error: - goto exit; -} - -static res_T -parse_receiver - (struct solreceivers* receivers, - yaml_document_t* doc, - const yaml_node_t* receiver) -{ - enum { NAME, SIDE }; - struct receiver* solreceiver = NULL; - size_t isolreceiver; - intptr_t i, n; - int mask = 0; /* Register the parsed attributes */ - res_T res = RES_OK; - ASSERT(receivers && doc && receiver); - - if(receiver->type != YAML_MAPPING_NODE) { - log_err(receivers, receiver, "expect a receiver definition.\n"); - res = RES_BAD_ARG; - goto error; - } - - /* Allocate the receiver */ - isolreceiver = darray_receiver_size_get(&receivers->receivers); - res = darray_receiver_resize(&receivers->receivers, isolreceiver + 1); - if(res != RES_OK) { - log_err(receivers, receiver, "could not allocate the receiver.\n"); - goto error; - } - solreceiver = darray_receiver_data_get(&receivers->receivers) + isolreceiver; - - n = receiver->data.mapping.pairs.top - receiver->data.mapping.pairs.start; - FOR_EACH(i, 0, n) { - yaml_node_t* key; - yaml_node_t* val; - - key = yaml_document_get_node(doc, receiver->data.mapping.pairs.start[i].key); - val = yaml_document_get_node(doc, receiver->data.mapping.pairs.start[i].value); - if(key->type != YAML_SCALAR_NODE) { - log_err(receivers, key, "expect receiver parameters.\n"); - res = RES_BAD_ARG; - goto error; - } - #define SETUP_MASK(Flag, Name) { \ - if(mask & BIT(Flag)) { \ - log_err(receivers, key, "the receiver "Name" is already defined.\n"); \ - res = RES_BAD_ARG; \ - goto error; \ - } \ - mask |= BIT(Flag); \ - } (void)0 - if(!strcmp((char*)key->data.scalar.value, "name")) { - SETUP_MASK(NAME, "name"); - res = parse_string(receivers, val, &solreceiver->name); - } else if(!strcmp((char*)key->data.scalar.value, "side")) { - SETUP_MASK(SIDE, "side"); - res = parse_side(receivers, val, &solreceiver->side); - } else { - log_err(receivers, key, "unknown receiver parameter `%s'.\n", - key->data.scalar.value); - res = RES_BAD_ARG; - } - if(res != RES_OK) goto error; - #undef SETUP_MASK - } - - if(!(mask & BIT(NAME))) { - log_err(receivers, receiver, "the receiver name is missing.\n"); - res = RES_BAD_ARG; - goto error; - } - -exit: - return res; -error: - if(solreceiver) darray_receiver_pop_back(&receivers->receivers); - goto exit; -} - -static void -receivers_clear(struct solreceivers* receivers) -{ - ASSERT(receivers); - darray_receiver_clear(&receivers->receivers); -} - -static void -receivers_release(ref_T* ref) -{ - struct solreceivers* receivers; - ASSERT(ref); - receivers = CONTAINER_OF(ref, struct solreceivers, ref); - if(receivers->parser_is_init) yaml_parser_delete(&receivers->parser); - str_release(&receivers->stream_name); - darray_receiver_release(&receivers->receivers); - MEM_RM(receivers->allocator, receivers); -} - -/******************************************************************************* - * Local functions - ******************************************************************************/ -res_T -solreceivers_create - (struct mem_allocator* allocater, struct solreceivers** out_receivers) -{ - struct solreceivers* receivers = NULL; - struct mem_allocator* mem_allocator; - res_T res = RES_OK; - ASSERT(out_receivers); - - mem_allocator = allocater ? allocater : &mem_default_allocator; - receivers = MEM_CALLOC(mem_allocator, 1, sizeof(struct solreceivers)); - if(!receivers) { - fprintf(stderr, "Could not allocate the loader of the receivers.\n"); - res = RES_MEM_ERR; - goto error; - } - receivers->allocator = mem_allocator; - ref_init(&receivers->ref); - str_init(mem_allocator, &receivers->stream_name); - darray_receiver_init(mem_allocator, &receivers->receivers); - -exit: - *out_receivers = receivers; - return res; -error: - if(receivers) { - solreceivers_ref_put(receivers); - receivers = NULL; - } - goto exit; -} - -void -solreceivers_ref_get(struct solreceivers* receivers) -{ - ASSERT(receivers); - ref_get(&receivers->ref); -} - -void -solreceivers_ref_put(struct solreceivers* receivers) -{ - ASSERT(receivers); - ref_put(&receivers->ref, receivers_release); -} - -res_T -solreceivers_setup_stream - (struct solreceivers* receivers, - const char* stream_name, - FILE* stream) -{ - res_T res = RES_OK; - ASSERT(receivers && stream); - - if(receivers->parser_is_init) { - yaml_parser_delete(&receivers->parser); - receivers->parser_is_init = 0; - } - - res = str_set(&receivers->stream_name, stream_name ? stream_name:"<stream>"); - if(res != RES_OK) { - fprintf(stderr, "Could not register the filename of the receiver stream.\n"); - goto error; - } - if(!yaml_parser_initialize(&receivers->parser)) { - fprintf(stderr, - "Could not initialise the YAML parser of the receiver stream.\n"); - res = RES_UNKNOWN_ERR; - goto error; - } - receivers->parser_is_init = 1; - yaml_parser_set_input_file(&receivers->parser, stream); - -exit: - return res; -error: - str_clear(&receivers->stream_name); - if(receivers->parser_is_init) { - yaml_parser_delete(&receivers->parser); - receivers->parser_is_init = 0; - } - goto exit; -} - -res_T -solreceivers_load(struct solreceivers* receivers) -{ - yaml_document_t doc; - yaml_node_t* root; - const char* stream_name; - intptr_t i, n; - int doc_is_init = 0; - res_T res = RES_OK; - ASSERT(receivers); - - stream_name = str_cget(&receivers->stream_name); - receivers_clear(receivers); /* Clean up previously loaded data */ - - if(!receivers->parser_is_init) { - res = RES_BAD_OP; - goto error; - } - - if(!yaml_parser_load(&receivers->parser, &doc)) { - fprintf(stderr, "%s:%lu:%lu: %s.\n", - stream_name, - (unsigned long)receivers->parser.problem_mark.line+1, - (unsigned long)receivers->parser.problem_mark.column+1, - receivers->parser.problem); - yaml_parser_delete(&receivers->parser); - receivers->parser_is_init = 0; - res = RES_BAD_OP; - goto error; - } - doc_is_init = 1; - - root = yaml_document_get_root_node(&doc); - if(!root) { - yaml_parser_delete(&receivers->parser); - receivers->parser_is_init = 0; - res = RES_BAD_OP; - goto error; - } - - if(root->type != YAML_SEQUENCE_NODE) { - log_err(receivers, root, "expect a list of receivers.\n"); - res = RES_BAD_ARG; - goto error; - } - - n = root->data.sequence.items.top - root->data.sequence.items.start; - FOR_EACH(i, 0, n) { - yaml_node_t* receiver; - - receiver = yaml_document_get_node(&doc, root->data.sequence.items.start[i]); - res = parse_receiver(receivers, &doc, receiver); - if(res != RES_OK) goto error; - } -exit: - if(doc_is_init) yaml_document_delete(&doc); - return res; -error: - receivers_clear(receivers); - goto exit; -} - -size_t -solreceivers_count(const struct solreceivers* receivers) -{ - ASSERT(receivers); - return darray_receiver_size_get(&receivers->receivers); -} - -void -solreceivers_get - (const struct solreceivers* receivers, - const size_t i, - struct solreceiver* receiver) -{ - const struct receiver* r; - ASSERT(receivers && receiver && i < solreceivers_count(receivers)); - r = darray_receiver_cdata_get(&receivers->receivers) + i; - receiver->name = str_cget(&r->name); - receiver->side = r->side; -} - diff --git a/src/receivers/solreceivers.h b/src/receivers/solreceivers.h @@ -1,73 +0,0 @@ -/* Copyright (C) CNRS 2016-2017 - * - * 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 SOLRECEIVERS_H -#define SOLRECEIVERS_H - -#include <rsys/rsys.h> - -enum solreceiver_side { - SOLRECEIVER_FRONT, - SOLRECEIVER_BACK, - SOLRECEIVER_FRONT_AND_BACK -}; - -struct solreceiver { - const char* name; - enum solreceiver_side side; -}; - -struct mem_allocator; -struct solreceivers; - -/******************************************************************************* - * Solstice Receiver API - ******************************************************************************/ -extern LOCAL_SYM res_T -solreceivers_create - (struct mem_allocator* allocator, /* May be NULL <=> use default allocator */ - struct solreceivers** receivers); - -extern LOCAL_SYM void -solreceivers_ref_get - (struct solreceivers* receivers); - -extern LOCAL_SYM void -solreceivers_ref_put - (struct solreceivers* receivers); - -extern LOCAL_SYM res_T -solreceivers_setup_stream - (struct solreceivers* receivers, - const char* stream_name, /* May be NULL */ - FILE* stream); - -/* Return RES_BAD_OP if there is no more YAML document to parse */ -extern LOCAL_SYM res_T -solreceivers_load - (struct solreceivers* receivers); - -extern LOCAL_SYM size_t -solreceivers_count - (const struct solreceivers* receivers); - -extern LOCAL_SYM void -solreceivers_get - (const struct solreceivers* receivers, - const size_t i, - struct solreceiver* receiver); - -#endif /* SOLRECEIVERS_H */ - diff --git a/src/receivers/srcvl.c b/src/receivers/srcvl.c @@ -0,0 +1,431 @@ +/* Copyright (C) CNRS 2016-2017 + * + * 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 "srcvl.h" + +#include <rsys/dynamic_array.h> +#include <rsys/mem_allocator.h> +#include <rsys/ref_count.h> +#include <rsys/str.h> + +#include <stdio.h> +#include <stdarg.h> +#include <yaml.h> + +struct receiver { + struct str name; + enum srcvl_side side; +}; + +static INLINE void +receiver_init(struct mem_allocator* allocator, struct receiver* receiver) +{ + ASSERT(receiver); + str_init(allocator, &receiver->name); + receiver->side = SRCVL_FRONT_AND_BACK; +} + +static INLINE void +receiver_release(struct receiver* receiver) +{ + ASSERT(receiver); + str_release(&receiver->name); +} + +static INLINE res_T +receiver_copy(struct receiver* dst, const struct receiver* src) +{ + ASSERT(dst && src); + dst->side = src->side; + return str_copy(&dst->name, &src->name); +} + + +static INLINE res_T +receiver_copy_and_release(struct receiver* dst, struct receiver* src) +{ + ASSERT(dst && src); + dst->side = src->side; + return str_copy_and_release(&dst->name, &src->name); +} + +#define DARRAY_NAME receiver +#define DARRAY_DATA struct receiver +#define DARRAY_FUNCTOR_INIT receiver_init +#define DARRAY_FUNCTOR_RELEASE receiver_release +#define DARRAY_FUNCTOR_COPY receiver_copy +#define DARRAY_FUNCTOR_COPY_AND_RELEASE receiver_copy_and_release +#include <rsys/dynamic_array.h> + +struct srcvl { + yaml_parser_t parser; + int parser_is_init; + struct darray_receiver receivers; + + struct str stream_name; + + ref_T ref; + struct mem_allocator* allocator; +}; + +/******************************************************************************* + * Helper functions + ******************************************************************************/ +static INLINE void +log_err + (const struct srcvl* srcvl, + const yaml_node_t* node, + const char* fmt, + ...) +{ + va_list vargs_list; + ASSERT(srcvl && node && fmt); + + fprintf(stderr, "%s:%lu:%lu: ", + str_cget(&srcvl->stream_name), + (unsigned long)node->start_mark.line+1, + (unsigned long)node->start_mark.column+1); + va_start(vargs_list, fmt); + vfprintf(stderr, fmt, vargs_list); + va_end(vargs_list); +} + +static res_T +parse_string + (struct srcvl* srcvl, + yaml_node_t* string, + struct str* str) +{ + res_T res = RES_OK; + ASSERT(string && str); + + if(string->type != YAML_SCALAR_NODE + || !strlen((char*)string->data.scalar.value)) { + log_err(srcvl, string, "expect a character string.\n"); + res = RES_BAD_ARG; + goto error; + } + res = str_set(str, (char*)string->data.scalar.value); + if(res != RES_OK) { + log_err(srcvl, string, "could not register the string `%s'.\n", + string->data.scalar.value); + goto error; + } + +exit: + return res; +error: + goto exit; +} + +static res_T +parse_side + (struct srcvl* srcvl, + yaml_node_t* side, + enum srcvl_side* out_side) +{ + res_T res = RES_OK; + ASSERT(side && out_side); + + if(side->type != YAML_SCALAR_NODE) { + log_err(srcvl, side, "expect a character string.\n"); + res = RES_BAD_ARG; + goto error; + } + + if(!strcmp((char*)side->data.scalar.value, "FRONT")) { + *out_side = SRCVL_FRONT; + } else if(!strcmp((char*)side->data.scalar.value, "BACK")) { + *out_side = SRCVL_BACK; + } else if(!strcmp((char*)side->data.scalar.value, "FRONT_AND_BACK")) { + *out_side = SRCVL_FRONT_AND_BACK; + } else { + log_err(srcvl, side, "unknown side valie `%s'.\n", + side->data.scalar.value); + res = RES_BAD_ARG; + goto error; + } +exit: + return res; +error: + goto exit; +} + +static res_T +parse_receiver + (struct srcvl* srcvl, + yaml_document_t* doc, + const yaml_node_t* receiver) +{ + enum { NAME, SIDE }; + struct receiver* solreceiver = NULL; + size_t isolreceiver; + intptr_t i, n; + int mask = 0; /* Register the parsed attributes */ + res_T res = RES_OK; + ASSERT(srcvl && doc && receiver); + + if(receiver->type != YAML_MAPPING_NODE) { + log_err(srcvl, receiver, "expect a receiver definition.\n"); + res = RES_BAD_ARG; + goto error; + } + + /* Allocate the receiver */ + isolreceiver = darray_receiver_size_get(&srcvl->receivers); + res = darray_receiver_resize(&srcvl->receivers, isolreceiver + 1); + if(res != RES_OK) { + log_err(srcvl, receiver, "could not allocate the receiver.\n"); + goto error; + } + solreceiver = darray_receiver_data_get(&srcvl->receivers) + isolreceiver; + + n = receiver->data.mapping.pairs.top - receiver->data.mapping.pairs.start; + FOR_EACH(i, 0, n) { + yaml_node_t* key; + yaml_node_t* val; + + key = yaml_document_get_node(doc, receiver->data.mapping.pairs.start[i].key); + val = yaml_document_get_node(doc, receiver->data.mapping.pairs.start[i].value); + if(key->type != YAML_SCALAR_NODE) { + log_err(srcvl, key, "expect receiver parameters.\n"); + res = RES_BAD_ARG; + goto error; + } + #define SETUP_MASK(Flag, Name) { \ + if(mask & BIT(Flag)) { \ + log_err(srcvl, key, "the receiver "Name" is already defined.\n"); \ + res = RES_BAD_ARG; \ + goto error; \ + } \ + mask |= BIT(Flag); \ + } (void)0 + if(!strcmp((char*)key->data.scalar.value, "name")) { + SETUP_MASK(NAME, "name"); + res = parse_string(srcvl, val, &solreceiver->name); + } else if(!strcmp((char*)key->data.scalar.value, "side")) { + SETUP_MASK(SIDE, "side"); + res = parse_side(srcvl, val, &solreceiver->side); + } else { + log_err(srcvl, key, "unknown receiver parameter `%s'.\n", + key->data.scalar.value); + res = RES_BAD_ARG; + } + if(res != RES_OK) goto error; + #undef SETUP_MASK + } + + if(!(mask & BIT(NAME))) { + log_err(srcvl, receiver, "the receiver name is missing.\n"); + res = RES_BAD_ARG; + goto error; + } + +exit: + return res; +error: + if(solreceiver) darray_receiver_pop_back(&srcvl->receivers); + goto exit; +} + +static void +receivers_clear(struct srcvl* srcvl) +{ + ASSERT(srcvl); + darray_receiver_clear(&srcvl->receivers); +} + +static void +receivers_release(ref_T* ref) +{ + struct srcvl* srcvl; + ASSERT(ref); + srcvl = CONTAINER_OF(ref, struct srcvl, ref); + if(srcvl->parser_is_init) yaml_parser_delete(&srcvl->parser); + str_release(&srcvl->stream_name); + darray_receiver_release(&srcvl->receivers); + MEM_RM(srcvl->allocator, srcvl); +} + +/******************************************************************************* + * Local functions + ******************************************************************************/ +res_T +srcvl_create + (struct mem_allocator* allocater, struct srcvl** out_receivers) +{ + struct srcvl* srcvl = NULL; + struct mem_allocator* mem_allocator; + res_T res = RES_OK; + ASSERT(out_receivers); + + mem_allocator = allocater ? allocater : &mem_default_allocator; + srcvl = MEM_CALLOC(mem_allocator, 1, sizeof(struct srcvl)); + if(!srcvl) { + fprintf(stderr, "Could not allocate the loader of the srcvl.\n"); + res = RES_MEM_ERR; + goto error; + } + srcvl->allocator = mem_allocator; + ref_init(&srcvl->ref); + str_init(mem_allocator, &srcvl->stream_name); + darray_receiver_init(mem_allocator, &srcvl->receivers); + +exit: + *out_receivers = srcvl; + return res; +error: + if(srcvl) { + srcvl_ref_put(srcvl); + srcvl = NULL; + } + goto exit; +} + +void +srcvl_ref_get(struct srcvl* srcvl) +{ + ASSERT(srcvl); + ref_get(&srcvl->ref); +} + +void +srcvl_ref_put(struct srcvl* srcvl) +{ + ASSERT(srcvl); + ref_put(&srcvl->ref, receivers_release); +} + +res_T +srcvl_setup_stream + (struct srcvl* srcvl, + const char* stream_name, + FILE* stream) +{ + res_T res = RES_OK; + ASSERT(srcvl && stream); + + if(srcvl->parser_is_init) { + yaml_parser_delete(&srcvl->parser); + srcvl->parser_is_init = 0; + } + + res = str_set(&srcvl->stream_name, stream_name ? stream_name:"<stream>"); + if(res != RES_OK) { + fprintf(stderr, "Could not register the filename of the receiver stream.\n"); + goto error; + } + if(!yaml_parser_initialize(&srcvl->parser)) { + fprintf(stderr, + "Could not initialise the YAML parser of the receiver stream.\n"); + res = RES_UNKNOWN_ERR; + goto error; + } + srcvl->parser_is_init = 1; + yaml_parser_set_input_file(&srcvl->parser, stream); + +exit: + return res; +error: + str_clear(&srcvl->stream_name); + if(srcvl->parser_is_init) { + yaml_parser_delete(&srcvl->parser); + srcvl->parser_is_init = 0; + } + goto exit; +} + +res_T +srcvl_load(struct srcvl* srcvl) +{ + yaml_document_t doc; + yaml_node_t* root; + const char* stream_name; + intptr_t i, n; + int doc_is_init = 0; + res_T res = RES_OK; + ASSERT(srcvl); + + stream_name = str_cget(&srcvl->stream_name); + receivers_clear(srcvl); /* Clean up previously loaded data */ + + if(!srcvl->parser_is_init) { + res = RES_BAD_OP; + goto error; + } + + if(!yaml_parser_load(&srcvl->parser, &doc)) { + fprintf(stderr, "%s:%lu:%lu: %s.\n", + stream_name, + (unsigned long)srcvl->parser.problem_mark.line+1, + (unsigned long)srcvl->parser.problem_mark.column+1, + srcvl->parser.problem); + yaml_parser_delete(&srcvl->parser); + srcvl->parser_is_init = 0; + res = RES_BAD_OP; + goto error; + } + doc_is_init = 1; + + root = yaml_document_get_root_node(&doc); + if(!root) { + yaml_parser_delete(&srcvl->parser); + srcvl->parser_is_init = 0; + res = RES_BAD_OP; + goto error; + } + + if(root->type != YAML_SEQUENCE_NODE) { + log_err(srcvl, root, "expect a list of srcvl.\n"); + res = RES_BAD_ARG; + goto error; + } + + n = root->data.sequence.items.top - root->data.sequence.items.start; + FOR_EACH(i, 0, n) { + yaml_node_t* receiver; + + receiver = yaml_document_get_node(&doc, root->data.sequence.items.start[i]); + res = parse_receiver(srcvl, &doc, receiver); + if(res != RES_OK) goto error; + } +exit: + if(doc_is_init) yaml_document_delete(&doc); + return res; +error: + receivers_clear(srcvl); + goto exit; +} + +size_t +srcvl_count(const struct srcvl* srcvl) +{ + ASSERT(srcvl); + return darray_receiver_size_get(&srcvl->receivers); +} + +void +srcvl_get + (const struct srcvl* srcvl, + const size_t i, + struct srcvl_receiver* receiver) +{ + const struct receiver* r; + ASSERT(srcvl && receiver && i < srcvl_count(srcvl)); + r = darray_receiver_cdata_get(&srcvl->receivers) + i; + receiver->name = str_cget(&r->name); + receiver->side = r->side; +} + diff --git a/src/receivers/srcvl.h b/src/receivers/srcvl.h @@ -0,0 +1,73 @@ +/* Copyright (C) CNRS 2016-2017 + * + * 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 SRCVL_H /* Solstice ReCeiVers Loader */ +#define SRCVL_H + +#include <rsys/rsys.h> + +enum srcvl_side { + SRCVL_FRONT, + SRCVL_BACK, + SRCVL_FRONT_AND_BACK +}; + +struct srcvl_receiver { + const char* name; + enum srcvl_side side; +}; + +struct mem_allocator; +struct srcvl; + +/******************************************************************************* + * Solstice Receiver API + ******************************************************************************/ +extern LOCAL_SYM res_T +srcvl_create + (struct mem_allocator* allocator, /* May be NULL <=> use default allocator */ + struct srcvl** rcvl); + +extern LOCAL_SYM void +srcvl_ref_get + (struct srcvl* rcvl); + +extern LOCAL_SYM void +srcvl_ref_put + (struct srcvl* rcvl); + +extern LOCAL_SYM res_T +srcvl_setup_stream + (struct srcvl* rcvl, + const char* stream_name, /* May be NULL */ + FILE* stream); + +/* Return RES_BAD_OP if there is no more YAML document to parse */ +extern LOCAL_SYM res_T +srcvl_load + (struct srcvl* rcvl); + +extern LOCAL_SYM size_t +srcvl_count + (const struct srcvl* rcvl); + +extern LOCAL_SYM void +srcvl_get + (const struct srcvl* rcvl, + const size_t i, + struct srcvl_receiver* receiver); + +#endif /* SRCVL_H */ + diff --git a/src/receivers/test_solreceivers.c b/src/receivers/test_solreceivers.c @@ -1,80 +0,0 @@ -/* Copyright (C) CNRS 2016-2017 - * - * 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 "solreceivers.h" -#include "test_solstice_utils.h" - -#include <string.h> - -int -main(int argc, char** argv) -{ - struct mem_allocator allocator; - struct solreceivers* receivers; - int ifile = 1; - int i; - res_T load_res = RES_OK; - (void)argc, (void)argv; - - if(argc > 1) { - if(!strcmp(argv[1], "-e")) { - load_res = RES_BAD_ARG; - ifile = 2; - } else if(!strcmp(argv[1], "-h")) { - printf("Usage: %s [OPTIONS] [FILE ... ]\n", argv[0]); - printf( -"Check the receiver API and that the submitted FILEs are valid. Use the `-e'\n" -"option to check that the FILEs are invalid.\n\n"); - printf("OPTIONS:\n"); - printf(" -h print this help and exit.\n"); - printf(" -e check that the submitted FILEs have errors.\n"); - return 0; - } - } - - CHECK(mem_init_proxy_allocator(&allocator, &mem_default_allocator), RES_OK); - solreceivers_create(&allocator, &receivers); - - CHECK(solreceivers_setup_stream(receivers, NULL, tmpfile()), RES_OK); - CHECK(solreceivers_setup_stream(receivers, "yop", tmpfile()), RES_OK); - CHECK(solreceivers_load(receivers), RES_BAD_OP); /* Empty stream */ - - FOR_EACH(i, ifile, argc) { - FILE* file = fopen(argv[i], "rb"); - int count = 0; - NCHECK(file, NULL); - CHECK(solreceivers_setup_stream(receivers, argv[i], file), RES_OK); - for(;;) { - const res_T res = solreceivers_load(receivers); - if(count == 0 && load_res == RES_OK) { - CHECK(res, RES_OK); - } else if(res == RES_BAD_OP) { - break; - } - CHECK(res, load_res); - ++count; - } - fclose(file); - } - solreceivers_ref_get(receivers); - solreceivers_ref_put(receivers); - solreceivers_ref_put(receivers); - - check_memory_allocator(&allocator); - mem_shutdown_proxy_allocator(&allocator); - CHECK(mem_allocated_size(), 0); - return 0; -} - diff --git a/src/receivers/test_solreceivers2.c b/src/receivers/test_solreceivers2.c @@ -1,94 +0,0 @@ -/* Copyright (C) CNRS 2016-2017 - * - * 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 "solreceivers.h" -#include "test_solstice_utils.h" - -#include <string.h> - -int -main(int argc, char** argv) -{ - struct mem_allocator allocator; - struct solreceivers* receivers; - struct solreceiver receiver; - FILE* stream; - int seek; - (void)argc, (void)argv; - - CHECK(mem_init_proxy_allocator(&allocator, &mem_default_allocator), RES_OK); - solreceivers_create(&allocator, &receivers); - - stream = tmpfile(); - NCHECK(stream, NULL); - fprintf(stream, "- { name: entity0 }\n"); - fprintf(stream, "- { name: \"entity1\" }\n"); - fprintf(stream, "- { name: entity2, side: FRONT }\n"); - fprintf(stream, "- { name: entity3, side: BACK }\n"); - fprintf(stream, "- name: entity4\n"); - fprintf(stream, " side: FRONT_AND_BACK\n"); - rewind(stream); - - CHECK(solreceivers_setup_stream(receivers, NULL, stream), RES_OK); - CHECK(solreceivers_load(receivers), RES_OK); - CHECK(solreceivers_count(receivers), 5); - - solreceivers_get(receivers, 0, &receiver); - CHECK(strcmp(receiver.name, "entity0"), 0); - CHECK(receiver.side, SOLRECEIVER_FRONT_AND_BACK); - - solreceivers_get(receivers, 1, &receiver); - CHECK(strcmp(receiver.name, "entity1"), 0); - CHECK(receiver.side, SOLRECEIVER_FRONT_AND_BACK); - - solreceivers_get(receivers, 2, &receiver); - CHECK(strcmp(receiver.name, "entity2"), 0); - CHECK(receiver.side, SOLRECEIVER_FRONT); - - solreceivers_get(receivers, 3, &receiver); - CHECK(strcmp(receiver.name, "entity3"), 0); - CHECK(receiver.side, SOLRECEIVER_BACK); - - solreceivers_get(receivers, 4, &receiver); - CHECK(strcmp(receiver.name, "entity4"), 0); - CHECK(receiver.side, SOLRECEIVER_FRONT_AND_BACK); - - CHECK(solreceivers_load(receivers), RES_BAD_OP); - - seek = (int)ftell(stream); - fprintf(stream, "---\n"); - fprintf(stream, "[{name: test 0, side: FRONT}, {name: test 1, side: BACK}]\n"); - fseek(stream, seek, SEEK_SET); - - CHECK(solreceivers_setup_stream(receivers, NULL, stream), RES_OK); - CHECK(solreceivers_load(receivers), RES_OK); - CHECK(solreceivers_count(receivers), 2); - - solreceivers_get(receivers, 0, &receiver); - CHECK(strcmp(receiver.name, "test 0"), 0); - CHECK(receiver.side, SOLRECEIVER_FRONT); - - solreceivers_get(receivers, 1, &receiver); - CHECK(strcmp(receiver.name, "test 1"), 0); - CHECK(receiver.side, SOLRECEIVER_BACK); - - fclose(stream); - solreceivers_ref_put(receivers); - - check_memory_allocator(&allocator); - mem_shutdown_proxy_allocator(&allocator); - CHECK(mem_allocated_size(), 0); - return 0; -} diff --git a/src/receivers/test_srcvl.c b/src/receivers/test_srcvl.c @@ -0,0 +1,80 @@ +/* Copyright (C) CNRS 2016-2017 + * + * 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 "srcvl.h" +#include "test_solstice_utils.h" + +#include <string.h> + +int +main(int argc, char** argv) +{ + struct mem_allocator allocator; + struct srcvl* srcvl; + int ifile = 1; + int i; + res_T load_res = RES_OK; + (void)argc, (void)argv; + + if(argc > 1) { + if(!strcmp(argv[1], "-e")) { + load_res = RES_BAD_ARG; + ifile = 2; + } else if(!strcmp(argv[1], "-h")) { + printf("Usage: %s [OPTIONS] [FILE ... ]\n", argv[0]); + printf( +"Check the receiver API and that the submitted FILEs are valid. Use the `-e'\n" +"option to check that the FILEs are invalid.\n\n"); + printf("OPTIONS:\n"); + printf(" -h print this help and exit.\n"); + printf(" -e check that the submitted FILEs have errors.\n"); + return 0; + } + } + + CHECK(mem_init_proxy_allocator(&allocator, &mem_default_allocator), RES_OK); + srcvl_create(&allocator, &srcvl); + + CHECK(srcvl_setup_stream(srcvl, NULL, tmpfile()), RES_OK); + CHECK(srcvl_setup_stream(srcvl, "yop", tmpfile()), RES_OK); + CHECK(srcvl_load(srcvl), RES_BAD_OP); /* Empty stream */ + + FOR_EACH(i, ifile, argc) { + FILE* file = fopen(argv[i], "rb"); + int count = 0; + NCHECK(file, NULL); + CHECK(srcvl_setup_stream(srcvl, argv[i], file), RES_OK); + for(;;) { + const res_T res = srcvl_load(srcvl); + if(count == 0 && load_res == RES_OK) { + CHECK(res, RES_OK); + } else if(res == RES_BAD_OP) { + break; + } + CHECK(res, load_res); + ++count; + } + fclose(file); + } + srcvl_ref_get(srcvl); + srcvl_ref_put(srcvl); + srcvl_ref_put(srcvl); + + check_memory_allocator(&allocator); + mem_shutdown_proxy_allocator(&allocator); + CHECK(mem_allocated_size(), 0); + return 0; +} + diff --git a/src/receivers/test_srcvl2.c b/src/receivers/test_srcvl2.c @@ -0,0 +1,94 @@ +/* Copyright (C) CNRS 2016-2017 + * + * 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 "srcvl.h" +#include "test_solstice_utils.h" + +#include <string.h> + +int +main(int argc, char** argv) +{ + struct mem_allocator allocator; + struct srcvl* srcvl; + struct srcvl_receiver receiver; + FILE* stream; + int seek; + (void)argc, (void)argv; + + CHECK(mem_init_proxy_allocator(&allocator, &mem_default_allocator), RES_OK); + srcvl_create(&allocator, &srcvl); + + stream = tmpfile(); + NCHECK(stream, NULL); + fprintf(stream, "- { name: entity0 }\n"); + fprintf(stream, "- { name: \"entity1\" }\n"); + fprintf(stream, "- { name: entity2, side: FRONT }\n"); + fprintf(stream, "- { name: entity3, side: BACK }\n"); + fprintf(stream, "- name: entity4\n"); + fprintf(stream, " side: FRONT_AND_BACK\n"); + rewind(stream); + + CHECK(srcvl_setup_stream(srcvl, NULL, stream), RES_OK); + CHECK(srcvl_load(srcvl), RES_OK); + CHECK(srcvl_count(srcvl), 5); + + srcvl_get(srcvl, 0, &receiver); + CHECK(strcmp(receiver.name, "entity0"), 0); + CHECK(receiver.side, SRCVL_FRONT_AND_BACK); + + srcvl_get(srcvl, 1, &receiver); + CHECK(strcmp(receiver.name, "entity1"), 0); + CHECK(receiver.side, SRCVL_FRONT_AND_BACK); + + srcvl_get(srcvl, 2, &receiver); + CHECK(strcmp(receiver.name, "entity2"), 0); + CHECK(receiver.side, SRCVL_FRONT); + + srcvl_get(srcvl, 3, &receiver); + CHECK(strcmp(receiver.name, "entity3"), 0); + CHECK(receiver.side, SRCVL_BACK); + + srcvl_get(srcvl, 4, &receiver); + CHECK(strcmp(receiver.name, "entity4"), 0); + CHECK(receiver.side, SRCVL_FRONT_AND_BACK); + + CHECK(srcvl_load(srcvl), RES_BAD_OP); + + seek = (int)ftell(stream); + fprintf(stream, "---\n"); + fprintf(stream, "[{name: test 0, side: FRONT}, {name: test 1, side: BACK}]\n"); + fseek(stream, seek, SEEK_SET); + + CHECK(srcvl_setup_stream(srcvl, NULL, stream), RES_OK); + CHECK(srcvl_load(srcvl), RES_OK); + CHECK(srcvl_count(srcvl), 2); + + srcvl_get(srcvl, 0, &receiver); + CHECK(strcmp(receiver.name, "test 0"), 0); + CHECK(receiver.side, SRCVL_FRONT); + + srcvl_get(srcvl, 1, &receiver); + CHECK(strcmp(receiver.name, "test 1"), 0); + CHECK(receiver.side, SRCVL_BACK); + + fclose(stream); + srcvl_ref_put(srcvl); + + check_memory_allocator(&allocator); + mem_shutdown_proxy_allocator(&allocator); + CHECK(mem_allocated_size(), 0); + return 0; +}