htcp

Properties of water suspended in clouds
git clone git://git.meso-star.fr/htcp.git
Log | Files | Refs | README | LICENSE

commit 550f6520e39bcef4b7f2cd11e33e17861362f892
parent d0792b02a7d78928e631f694d6c97480953a7159
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Fri, 27 Apr 2018 16:22:58 +0200

Rename the htnc lib in htcop and begin its implementation

Write some tests

Diffstat:
Mcmake/CMakeLists.txt | 66+++++++++++++++++++++++++++++++++---------------------------------
Asrc/htcop.c | 256+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/htcop.h | 90+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/htnc.c | 253-------------------------------------------------------------------------------
Dsrc/htnc.h | 81-------------------------------------------------------------------------------
Msrc/les2htcop.c | 4++--
Asrc/test_htcop.c | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/test_htcop_load.c | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/test_htcop_utils.h | 34++++++++++++++++++++++++++++++++++
9 files changed, 545 insertions(+), 369 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -14,13 +14,14 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. cmake_minimum_required(VERSION 2.8) -project(htnc C) +project(htcop C) enable_testing() -set(HTNC_SOURCE_DIR ${PROJECT_SOURCE_DIR}/../src) option(NO_TEST "Do not build tests" OFF) -add_subdirectory(les2htcop) +add_subdirectory(les2htcop) # Build utility + +set(HTCOP_SOURCE_DIR ${PROJECT_SOURCE_DIR}/../src) ################################################################################ # Check dependencies @@ -30,13 +31,12 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${_current_source_dir}/) find_package(RCMake 0.3 REQUIRED) find_package(RSys 0.6 REQUIRED) -find_package(NetCDF REQUIRED) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${RCMAKE_SOURCE_DIR}) include(rcmake) include(rcmake_runtime) -include_directories(${RSys_INCLUDE_DIR} ${NETCDF_C_INCLUDE_DIRS}) +include_directories(${RSys_INCLUDE_DIR}) ################################################################################ # Configure and define targets @@ -46,27 +46,26 @@ set(VERSION_MINOR 0) set(VERSION_PATCH 0) set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) -set(HTNC_FILES_SRC htnc.c) -set(HTNC_FILES_INC ) -set(HTNC_FILES_INC_API htnc.h) -set(HTNC_FILES_DOC COPYING) +set(HTCOP_FILES_SRC htcop.c) +set(HTCOP_FILES_INC ) +set(HTCOP_FILES_INC_API htcop.h) +set(HTCOP_FILES_DOC COPYING) -# Prepend each file in the `HTNC_FILES_<SRC|INC>' list by `HTNC_SOURCE_DIR' -rcmake_prepend_path(HTNC_FILES_SRC ${HTNC_SOURCE_DIR}) -rcmake_prepend_path(HTNC_FILES_INC ${HTNC_SOURCE_DIR}) -rcmake_prepend_path(HTNC_FILES_INC_API ${HTNC_SOURCE_DIR}) -rcmake_prepend_path(HTNC_FILES_DOC ${PROJECT_SOURCE_DIR}/../) +# Prepend each file in the `HTCOP_FILES_<SRC|INC>' list by `HTCOP_SOURCE_DIR' +rcmake_prepend_path(HTCOP_FILES_SRC ${HTCOP_SOURCE_DIR}) +rcmake_prepend_path(HTCOP_FILES_INC ${HTCOP_SOURCE_DIR}) +rcmake_prepend_path(HTCOP_FILES_INC_API ${HTCOP_SOURCE_DIR}) +rcmake_prepend_path(HTCOP_FILES_DOC ${PROJECT_SOURCE_DIR}/../) -#add_library(htnc SHARED ${HTNC_FILES_SRC} ${HTNC_FILES_INC} ${HTNC_FILES_INC_API}) -#target_link_libraries(htnc RSys ${NETCDF_C_LIBRARIES}) -# -#set_target_properties(htnc PROPERTIES -# DEFINE_SYMBOL HTNC_SHARED_BUILD -# VERSION ${VERSION} -# SOVERSION ${VERSION_MAJOR}) -# -#rcmake_setup_devel(htnc HTNC ${VERSION} high_tune/htnc.h) -# +add_library(htcop SHARED ${HTCOP_FILES_SRC} ${HTCOP_FILES_INC} ${HTCOP_FILES_INC_API}) +target_link_libraries(htcop RSys) + +set_target_properties(htcop PROPERTIES + DEFINE_SYMBOL HTCOP_SHARED_BUILD + VERSION ${VERSION} + SOVERSION ${VERSION_MAJOR}) + +rcmake_setup_devel(htcop HTCOP ${VERSION} high_tune/htcop.h) ################################################################################ # Add tests @@ -74,8 +73,8 @@ rcmake_prepend_path(HTNC_FILES_DOC ${PROJECT_SOURCE_DIR}/../) if(NOT NO_TEST) function(build_test _name) add_executable(${_name} - ${HTNC_SOURCE_DIR}/${_name}.c) - target_link_libraries(${_name} RSys ${NETCDF_C_LIBRARIES}) + ${HTCOP_SOURCE_DIR}/${_name}.c) + target_link_libraries(${_name} htcop) endfunction() function(new_test _name) @@ -83,16 +82,17 @@ if(NOT NO_TEST) add_test(${_name} ${_name}) endfunction() + new_test(test_htcop) + new_test(test_htcop_load) endif() - ################################################################################ # Define output & install directories ################################################################################ +install(TARGETS htcop + ARCHIVE DESTINATION bin + LIBRARY DESTINATION lib + RUNTIME DESTINATION bin) +install(FILES ${HTCOP_FILES_INC_API} DESTINATION include/high_tune) +install(FILES ${HTCOP_FILES_DOC} DESTINATION share/doc/htcop) -#install(TARGETS htgop -# ARCHIVE DESTINATION bin -# LIBRARY DESTINATION lib -# RUNTIME DESTINATION bin) -#install(FILES ${HTNC_FILES_INC_API} DESTINATION include/high_tune) -#install(FILES ${HTNC_FILES_DOC} DESTINATION share/doc/htgop) diff --git a/src/htcop.c b/src/htcop.c @@ -0,0 +1,256 @@ +/* Copyright (C) 2018 |Meso|Star> (contact@meso-star.com) + * + * 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 200809L /* mmap support */ +#define _DEFAULT_SOURCE 1 /* MAP_POPULATE support */ + +#include "htcop.h" + +#include <rsys/dynamic_array_double.h> +#include <rsys/logger.h> +#include <rsys/ref_count.h> +#include <rsys/mem_allocator.h> + +#include <errno.h> +#include <string.h> +#include <sys/mman.h> + +enum { X, Y, Z, TIME }; /* Helper constants */ + +struct htcop { + int8_t irregular_z; + int32_t definition[4]; + double lower[3]; + double vxsz[2]; /* Size of the voxels in X and Y */ + struct darray_double vxsz_z; /* Size of the voxels along the Z dimension */ + + double* RCT; /* Mapped memory */ + double* RVT; /* Mapped memory */ + + int verbose; /* Verbosity level */ + struct logger* logger; + struct mem_allocator* allocator; + ref_T ref; +}; + +/******************************************************************************* + * Local functions + ******************************************************************************/ +static void +log_msg + (const struct htcop* htcop, + const enum log_type stream, + const char* msg, + va_list vargs) +{ + ASSERT(htcop && msg); + if(htcop->verbose) { + res_T res; (void)res; + res = logger_vprint(htcop->logger, stream, msg, vargs); + ASSERT(res == RES_OK); + } +} + +static void +log_err(const struct htcop* htcop, const char* msg, ...) +{ + va_list vargs_list; + ASSERT(htcop && msg); + va_start(vargs_list, msg); + log_msg(htcop, LOG_ERROR, msg, vargs_list); + va_end(vargs_list); +} + +static res_T +load_stream(struct htcop* htcop, FILE* stream, const char* stream_name) +{ + size_t nz = 0; + size_t map_len = 0; + off_t offset = 0; + res_T res = RES_OK; + ASSERT(htcop && stream && stream_name); + + #define READ(Var, N, Name) { \ + if(fread((Var), sizeof(*(Var)), (N), stream) != (N)) { \ + fprintf(stderr, "%s: could not read the %s\n", stream_name, Name); \ + res = RES_IO_ERR; \ + goto error; \ + } \ + } (void)0 + READ(&htcop->irregular_z, 1, "'irregular Z' flag"); + READ(htcop->definition, 4, "spatial and time definitions"); + READ(htcop->lower, 3, "lower position"); + READ(htcop->vxsz, 2, "XY voxel size "); + + nz = htcop->irregular_z ? (size_t)htcop->definition[Z] : 1; + res = darray_double_resize(&htcop->vxsz_z, nz); + if(res != RES_OK) { + fprintf(stderr, + "%s: could not allocate memory to store the size of the voxels in Z.\n", + stream_name); + res = RES_MEM_ERR; + goto error; + } + READ(darray_double_data_get(&htcop->vxsz_z), nz, "Z voxel size(s)"); + #undef READ + + map_len = + (size_t)htcop->definition[X] + * (size_t)htcop->definition[Y] + * (size_t)htcop->definition[Z] + * (size_t)htcop->definition[TIME] + * sizeof(double); + + if(map_len == 0) { + fprintf(stderr, "%s: the spatial/time definition cannot be null.\n", + stream_name); + res = RES_BAD_ARG; + goto error; + } + + offset = ftell(stream); + + #define MMAP(Var) { \ + htcop->Var = mmap(NULL, map_len, PROT_READ, MAP_PRIVATE|MAP_POPULATE, \ + fileno(stream), offset); \ + if(htcop->Var == MAP_FAILED) { \ + fprintf(stderr, "%s: could not map the "STR(Var)" data -- %s.\n", \ + stream_name, strerror(errno)); \ + res = RES_IO_ERR; \ + goto error; \ + } \ + } (void)0 + MMAP(RVT); offset += (off_t)map_len; + MMAP(RCT); offset += (off_t)map_len; + #undef MMAP + + CHK(fseek(stream, offset, SEEK_CUR) != -1); + +exit: + return res; +error: + goto exit; +} + +static void +release_htcop(ref_T* ref) +{ + struct htcop* htcop; + ASSERT(ref); + htcop = CONTAINER_OF(ref, struct htcop, ref); + darray_double_release(&htcop->vxsz_z); + MEM_RM(htcop->allocator, htcop); +} + +/******************************************************************************* + * Exported functions + ******************************************************************************/ +res_T +htcop_create + (struct logger* log, + struct mem_allocator* mem_allocator, + const int verbose, + struct htcop** out_htcop) +{ + struct htcop* htcop = NULL; + struct mem_allocator* allocator = NULL; + struct logger* logger = NULL; + res_T res = RES_OK; + + if(!out_htcop) { + res = RES_BAD_ARG; + goto error; + } + + allocator = mem_allocator ? mem_allocator : &mem_default_allocator; + logger = log ? log : LOGGER_DEFAULT; + + htcop = MEM_CALLOC(allocator, 1, sizeof(struct htcop)); + if(!htcop) { + if(verbose) { + logger_print(logger, LOG_ERROR, + "%s: could not allocate the HTCOP handler.\n", FUNC_NAME); + res = RES_MEM_ERR; + goto error; + } + } + ref_init(&htcop->ref); + htcop->allocator = allocator; + htcop->logger = logger; + htcop->verbose = verbose; + darray_double_init(htcop->allocator, &htcop->vxsz_z); + +exit: + if(out_htcop) *out_htcop = htcop; + return res; +error: + if(htcop) { + HTCOP(ref_put(htcop)); + htcop = NULL; + } + goto exit; +} + +res_T +htcop_ref_get(struct htcop* htcop) +{ + if(!htcop) return RES_BAD_ARG; + ref_get(&htcop->ref); + return RES_OK; +} + +res_T +htcop_ref_put(struct htcop* htcop) +{ + if(!htcop) return RES_BAD_ARG; + ref_put(&htcop->ref, release_htcop); + return RES_OK; +} + +res_T +htcop_load(struct htcop* htcop, const char* path) +{ + FILE* file = NULL; + res_T res = RES_OK; + + if(!htcop || !path) { + res = RES_BAD_ARG; + goto error; + } + + file = fopen(path, "r"); + if(!file) { + log_err(htcop, "%s: error opening file `%S'.\n", FUNC_NAME, path); + res = RES_IO_ERR; + goto error; + } + + res = load_stream(htcop, file, path); + if(res != RES_OK) goto error; + +exit: + if(file) fclose(file); + return res; +error: + goto exit; +} + +res_T +htcop_load_stream(struct htcop* htcop, FILE* stream) +{ + if(!htcop || !stream) return RES_BAD_ARG; + return load_stream(htcop, stream, "<stream>"); +} + diff --git a/src/htcop.h b/src/htcop.h @@ -0,0 +1,90 @@ +/* Copyright (C) 2018 |Meso|Star> (contact@meso-star.com) + * + * 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 HTCOP_H +#define HTCOP_H + +#include <rsys/rsys.h> + +/* Library symbol management */ +#if defined(HTCOP_SHARED_BUILD) /* Build shared library */ + #define HTCOP_API extern EXPORT_SYM +#elif defined(HTCOP_STATIC) /* Use/build static library */ + #define HTCOP_API extern LOCAL_SYM +#else /* Use shared library */ + #define HTCOP_API extern IMPORT_SYM +#endif + +/* Helper macro that asserts if the invocation of the htcop function `Func' + * returns an error. One should use this macro on htcop function calls for + * which no explicit error checking is performed */ +#ifndef NDEBUG + #define HTCOP(Func) ASSERT(htcop_ ## Func == RES_OK) +#else + #define HTCOP(Func) htcop_ ## Func +#endif + +/* Forward declaration of external data types */ +struct logger; +struct mem_allocator; + +/* Forward declaration of opaque data types */ +struct htcop; + +struct htcop_layout { + /* #coordinates along the X, Y and Z axis. X means for the West-Est axis, Y + * is the South-North axis and finally Z is the altitude */ + size_t spatial_definition[3]; + size_t time_definition; /* Definition of the time */ +}; + +BEGIN_DECLS + +/******************************************************************************* + * HTCOP API + ******************************************************************************/ +HTCOP_API res_T +htcop_create +(struct logger* logger, /* NULL <=> use default logger */ + struct mem_allocator* allocator, /* NULL <=> use default allocator */ + const int verbose, /* Verbosity level */ + struct htcop** htcop); + +HTCOP_API res_T +htcop_load + (struct htcop* htcop, + const char* path); + +HTCOP_API res_T +htcop_load_stream + (struct htcop* htcop, + FILE* stream); + +HTCOP_API res_T +htcop_ref_get + (struct htcop* htcop); + +HTCOP_API res_T +htcop_ref_put + (struct htcop* htcop); + +HTCOP_API res_T +htcop_get_layout + (const struct htcop* htcop, + struct htcop_layout* layout); + +END_DECLS + +#endif /* HTCOP_H */ diff --git a/src/htnc.c b/src/htnc.c @@ -1,253 +0,0 @@ -/* Copyright (C) 2018 |Meso|Star> (contact@meso-star.com) - * - * 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 "htnc.h" - -#include <rsys/logger.h> -#include <rsys/ref_count.h> -#include <rsys/mem_allocator.h> - -#include <netcdf.h> - -#define INVALID_NC_ID - 1 - -#define NC(Func) { \ - const int err__ = nc_ ## Func; \ - if(err__ != NC_NOERR) { \ - fprintf(stderr, "error:%s:%i:%s:%s\n", \ - __FILE__, __LINE__, FUNC_NAME, nc_err_to_str(err__)); \ - abort(); \ - } \ - } (void)0 - -struct htnc { - size_t spatial_definition[3]; - nc_type spatial_type; - - const char* filename; - int nc; /* NetCDF handle */ - - int verbose; - struct logger* logger; - struct mem_allocator* allocator; - ref_T ref; -}; - -/******************************************************************************* - * Local functions - ******************************************************************************/ -static INLINE const char* -nc_err_to_str(const int ncerr) -{ - const char* str = "NC_ERR_<UNKNOWN>"; - switch(ncerr) { - case NC_EBADGRPID: str = "NC_EBADGRPID"; break; - case NC_EBADID: str = "NC_EBADID"; break; - case NC_EBADNAME: str = "NC_EBADNAME"; break; - case NC_ECHAR: str = "NC_ECHAR"; break; - case NC_EDIMMETA: str = "NC_EDIMMETA"; break; - case NC_EHDFERR: str = "NC_EHDFERR"; break; - case NC_ENOMEM: str = "NC_ENOMEM"; break; - case NC_ENOTATT: str = "NC_ENOTATT"; break; - case NC_ENOTVAR: str = "NC_ENOTVAR"; break; - case NC_ERANGE: str = "NC_ERANGE"; break; - case NC_NOERR: str = "NC_NOERR"; break; - } - return str; -} - -static INLINE const char* -nc_type_to_str(const nc_type type) -{ - const char* str = "NC_TYPE_<UNKNOWN>"; - switch(type) { - case NC_NAT: str = "NC_NAT"; break; - case NC_BYTE: str = "NC_BYTE"; break; - case NC_CHAR: str = "NC_CHAR"; break; - case NC_SHORT: str = "NC_SHORT"; break; - case NC_INT: str = "NC_INT"; break; - case NC_FLOAT: str = "NC_FLOAT"; break; - case NC_DOUBLE: str = "NC_DOUBLE"; break; - case NC_UBYTE: str = "NC_UBYTE"; break; - case NC_USHORT: str = "NC_USHORT"; break; - case NC_UINT64: str = "NC_UINT64"; break; - case NC_STRING: str = "NC_STRING"; break; - default: FATAL("Unreachable code.\n"); break; - } - return str; -} - -static void -log_msg - (const struct htnc* htnc, - const enum log_type stream, - const char* msg, - va_list vargs) -{ - ASSERT(htnc && msg); - if(htnc->verbose) { - res_T res; (void)res; - res = logger_vprint(htnc->logger, stream, msg, vargs); - ASSERT(res == RES_OK); - } -} - -static void -log_err(const struct htnc* htnc, const char* msg, ...) -{ - va_list vargs_list; - ASSERT(htnc && msg); - va_start(vargs_list, msg); - log_msg(htnc, LOG_ERROR, msg, vargs_list); - va_end(vargs_list); -} - -static res_T -inquire_W_E_direction(struct htnc* htnc) -{ - int nc_err = NC_NOERR; - int nc_var = INVALID_NC_ID; - int nc_dim = INVALID_NC_ID; - int ndims = 0; - size_t len = 0; - nc_type type = NC_NAT; - res_T res = RES_OK; - ASSERT(htnc); - - nc_err = nc_inq_varid(htnc->nc, "W_E_direction", &nc_var); - if(nc_err != NC_NOERR) { - log_err(htnc, - "%s:%s: could not retrieve the variable `W_E_direction' -- %s.\n", - FUNC_NAME, htnc->filename, nc_err_to_str(nc_err)); - res = RES_BAD_ARG; - goto error; - } - NC(inq_var(htnc->nc, nc_var, NULL, &type, &ndims, NULL, NULL)); - if(type != NC_FLOAT || type != NC_DOUBLE) { - log_err(htnc, - "%s:%s: expecting floating-point data type. The read type is `%s'.\n", - FUNC_NAME, htnc->filename, nc_type_to_str(type)); - res = RES_BAD_ARG; - goto error; - } - if(ndims > 1) { - log_err(htnc, - "%s:%s: expecting a 1D array. The read #dimensions `%i'.\n", - FUNC_NAME, htnc->filename, ndims); - res = RES_BAD_ARG; - goto error; - } - NC(inq_var(htnc->nc, nc_var, NULL, NULL, NULL, &nc_dim, NULL)); - NC(inq_dim(htnc->nc, nc_dim, NULL, &len)); - - htnc->spatial_definition[0] = len; -exit: - return res; -error: - goto exit; -} - -static void -release_htnc(ref_T* ref) -{ - struct htnc* htnc; - ASSERT(ref); - - htnc = CONTAINER_OF(ref, struct htnc, ref); - if(htnc->nc != INVALID_NC_ID) NC(close(htnc->nc)); - MEM_RM(htnc->allocator, htnc); -} - -/******************************************************************************* - * Exported functions - ******************************************************************************/ -res_T -htnc_open - (const char* path, - struct logger* log, - struct mem_allocator* mem_allocator, - const int verbose, - struct htnc** out_htnc) -{ - struct htnc* htnc = NULL; - struct mem_allocator* allocator = NULL; - struct logger* logger = NULL; - int nc_err = NC_NOERR; - res_T res = RES_OK; - - if(!out_htnc) { - res = RES_BAD_ARG; - goto error; - } - - allocator = mem_allocator ? mem_allocator : &mem_default_allocator; - logger = log ? log : LOGGER_DEFAULT; - - htnc = MEM_CALLOC(allocator, 1, sizeof(struct htnc)); - if(!htnc) { - if(verbose) { - logger_print(logger, LOG_ERROR, - "%s: could not allocate the HTNC handler.\n", FUNC_NAME); - res = RES_MEM_ERR; - goto error; - } - } - ref_init(&htnc->ref); - htnc->filename = path; - htnc->allocator = allocator; - htnc->nc = INVALID_NC_ID; - htnc->verbose = verbose; - - /* Open the NetCDF file */ - nc_err = nc_open(path, NC_WRITE|NC_MMAP, &htnc->nc); - if(nc_err != NC_NOERR) { - log_err(htnc, "%s: cannot open the file `%s' -- %s\n", - FUNC_NAME, path, nc_err_to_str(nc_err)); - res = RES_IO_ERR; - goto error; - } - - res = inquire_W_E_direction(htnc); - if(res != RES_OK) goto error; - - /* TODO inquire the other data */ - -exit: - if(out_htnc) *out_htnc = htnc; - return res; -error: - if(htnc) { - HTNC(ref_put(htnc)); - htnc = NULL; - } - goto exit; -} - -res_T -htnc_ref_get(struct htnc* htnc) -{ - if(!htnc) return RES_BAD_ARG; - ref_get(&htnc->ref); - return RES_OK; -} - -res_T -htnc_ref_put(struct htnc* htnc) -{ - if(!htnc) return RES_BAD_ARG; - ref_put(&htnc->ref, release_htnc); - return RES_OK; -} - diff --git a/src/htnc.h b/src/htnc.h @@ -1,81 +0,0 @@ -/* Copyright (C) 2018 |Meso|Star> (contact@meso-star.com) - * - * 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 HTNC_H -#define HTNC_H - -#include <rsys/rsys.h> - -/* Library symbol management */ -#if defined(HTNC_SHARED_BUILD) /* Build shared library */ - #define HTNC_API extern EXPORT_SYM -#elif defined(HTNC_STATIC) /* Use/build static library */ - #define HTNC_API extern LOCAL_SYM -#else /* Use shared library */ - #define HTNC_API extern IMPORT_SYM -#endif - -/* Helper macro that asserts if the invocation of the htnc function `Func' - * returns an error. One should use this macro on htnc function calls for - * which no explicit error checking is performed */ -#ifndef NDEBUG - #define HTNC(Func) ASSERT(htnc_ ## Func == RES_OK) -#else - #define HTNC(Func) htnc_ ## Func -#endif - -/* Forward declaration of external data types */ -struct logger; -struct mem_allocator; - -/* Forward declaration of opaque data types */ -struct htnc; - -struct htnc_layout { - /* #coordinates along the X, Y and Z axis. X means for the West-Est axis, Y - * is the South-North axis and finally Z is the altitude */ - size_t spatial_definition[3]; - size_t time_definition; /* Definition of the time */ -}; - -BEGIN_DECLS - -/******************************************************************************* - * HTNC API - ******************************************************************************/ -HTNC_API res_T -htnc_open - (const char* path, - struct logger* logger, - struct mem_allocator* allocator, - const int verbose, - struct htnc** htnc); - -HTNC_API res_T -htnc_ref_get - (struct htnc* htnc); - -HTNC_API res_T -htnc_ref_put - (struct htnc* htnc); - -HTNC_API res_T -htnc_get_layout - (const struct htnc* htnc, - struct htnc_layout* layout); - -END_DECLS - -#endif /* HTNC_H */ diff --git a/src/les2htcop.c b/src/les2htcop.c @@ -687,8 +687,8 @@ main(int argc, char** argv) #undef CALL #define WRITE(Var, N, Name) { \ - if(fwrite(Var, sizeof(*Var), (N), stream) != (N)) { \ - fprintf(stderr, "Error writing the %s.\n", Name); \ + if(fwrite((Var), sizeof(*(Var)), (N), stream) != (N)) { \ + fprintf(stderr, "Error writing the %s.\n", (Name)); \ res = RES_IO_ERR; \ goto error; \ } \ diff --git a/src/test_htcop.c b/src/test_htcop.c @@ -0,0 +1,65 @@ +/* Copyright (C) 2018 |Meso|Star> (contact@meso-star.com) + * + * 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 "htcop.h" +#include "test_htcop_utils.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 htcop* htcop = NULL; + (void)argc, (void)argv; + + CHK(htcop_create(NULL, NULL, 0, NULL) == RES_BAD_ARG); + CHK(htcop_create(NULL, NULL, 0, &htcop) == RES_OK); + + CHK(htcop_ref_get(NULL) == RES_BAD_ARG); + CHK(htcop_ref_get(htcop) == RES_OK); + CHK(htcop_ref_put(NULL) == RES_BAD_ARG); + CHK(htcop_ref_put(htcop) == RES_OK); + CHK(htcop_ref_put(htcop) == RES_OK); + + CHK(mem_init_proxy_allocator(&allocator, &mem_default_allocator) == RES_OK); + CHK(htcop_create(NULL, &allocator, 1, &htcop) == RES_OK); + CHK(htcop_ref_put(htcop) == 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); + + CHK(htcop_create(&logger, &allocator, 0, &htcop) == RES_OK); + CHK(htcop_ref_put(htcop) == RES_OK); + CHK(htcop_create(&logger, NULL, 0, &htcop) == RES_OK); + CHK(htcop_ref_put(htcop) == RES_OK); + + logger_release(&logger); + check_memory_allocator(&allocator); + mem_shutdown_proxy_allocator(&allocator); + CHK(mem_allocated_size() == 0); + return 0; +} diff --git a/src/test_htcop_load.c b/src/test_htcop_load.c @@ -0,0 +1,65 @@ +/* Copyright (C) 2018 |Meso|Star> (contact@meso-star.com) + * + * 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 "htcop.h" +#include "test_htcop_utils.h" + +int +main(int argc, char** argv) +{ + struct htcop* htcop = NULL; + FILE* stream = NULL; + int8_t i8; + int32_t i32[4]; + double dbl[3]; + size_t i; + (void)argc, (void)argv; + + stream = tmpfile(); + + i8 = 0; + CHK(fwrite(&i8, sizeof(i8), 1, stream) == 1); + i32[0] = 2; + i32[1] = 2; + i32[2] = 3; + i32[3] = 1; + CHK(fwrite(i32, sizeof(i32[0]), 4, stream) == 4); + dbl[0] = 0; + dbl[1] = 0; + dbl[2] = 0; + CHK(fwrite(dbl, sizeof(dbl[0]), 3, stream) == 3); + dbl[0] = 1; + dbl[1] = 2; + dbl[2] = 3; + CHK(fwrite(dbl, sizeof(dbl[0]), 3, stream) == 3); + FOR_EACH(i, 0, i32[0]*i32[1]*i32[2]*i32[3]) { /* RVT */ + dbl[0] = (double)i; + CHK(fwrite(dbl, sizeof(dbl[0]), 1, stream) == 1); + } + + FOR_EACH(i, 0, i32[0]*i32[1]*i32[2]*i32[3]) { /* RCT */ + dbl[0] = (double)i; + CHK(fwrite(dbl, sizeof(dbl[0]), 1, stream) == 1); + } + + rewind(stream); + + CHK(htcop_create(NULL, &mem_default_allocator, 1, &htcop) == RES_OK); + CHK(htcop_load_stream(htcop, stream) == RES_OK); + CHK(htcop_ref_put(htcop) == RES_OK); + + CHK(mem_allocated_size() == 0); + return 0; +} diff --git a/src/test_htcop_utils.h b/src/test_htcop_utils.h @@ -0,0 +1,34 @@ +/* Copyright (C) 2018 |Meso|Star> (contact@meso-star.com) + * + * 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 TEST_HTCOP_UTILS_H +#define TEST_HTCOP_UTILS_H + +#include <rsys/mem_allocator.h> +#include <stdio.h> + +static INLINE void +check_memory_allocator(struct mem_allocator* allocator) +{ + if(MEM_ALLOCATED_SIZE(allocator)) { + char dump[512]; + MEM_DUMP(allocator, dump, sizeof(dump)/sizeof(char)); + fprintf(stderr, "%s\n", dump); + FATAL("Memory leaks\n"); + } +} + +#endif /* TEST_HTCOP_UTILS_H */ +