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:
| M | cmake/CMakeLists.txt | | | 66 | +++++++++++++++++++++++++++++++++--------------------------------- |
| A | src/htcop.c | | | 256 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | src/htcop.h | | | 90 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| D | src/htnc.c | | | 253 | ------------------------------------------------------------------------------- |
| D | src/htnc.h | | | 81 | ------------------------------------------------------------------------------- |
| M | src/les2htcop.c | | | 4 | ++-- |
| A | src/test_htcop.c | | | 65 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | src/test_htcop_load.c | | | 65 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | src/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 */
+