diff --git a/Makefile.am b/Makefile.am index 1949d62..12bd70f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -31,7 +31,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ACLOCAL_AMFLAGS = -I m4 -CLEANFILES = +CLEANFILES = trexio.mod VERSION_MAJOR = @VERSION_MAJOR@ VERSION_MINOR = @VERSION_MINOR@ @@ -81,13 +81,16 @@ tests_test_c_LDFLAGS = -no-install test_trexio_f = $(srcdir)/tests/trexio_f.f90 -tests_test_f_SOURCES = tests/test_f.f90 $(test_trexio_f) +tests_test_f_SOURCES = $(test_trexio_f) tests/test_f.f90 tests_test_f_LDADD = src/libtrexio.la tests_test_f_LDFLAGS = -no-install -$(test_trexio_f): $(trexio_f) +$(test_trexio_f): cp $(trexio_f) $(test_trexio_f) +clean-local: + -rm -rf -- test_write.dir/ test_write_f.dir/ test_write.h5 + if TREXIO_DEVEL CLEANFILES += $(SOURCES) $(trexio_f) $(trexio_h) diff --git a/src/templates_front/templator_front.org b/src/templates_front/templator_front.org index 8ba9f9f..971ac89 100644 --- a/src/templates_front/templator_front.org +++ b/src/templates_front/templator_front.org @@ -115,31 +115,32 @@ typedef int32_t trexio_exit_code; ** Error handling #+NAME: table-exit-codes - | Macro | Code | Description | - |-----------------------------+------+---------------------------| - | ~TREXIO_FAILURE~ | -1 | 'Unknown failure' | - | ~TREXIO_SUCCESS~ | 0 | 'Success' | - | ~TREXIO_INVALID_ARG_1~ | 1 | 'Invalid argument 1' | - | ~TREXIO_INVALID_ARG_2~ | 2 | 'Invalid argument 2' | - | ~TREXIO_INVALID_ARG_3~ | 3 | 'Invalid argument 3' | - | ~TREXIO_INVALID_ARG_4~ | 4 | 'Invalid argument 4' | - | ~TREXIO_INVALID_ARG_5~ | 5 | 'Invalid argument 5' | - | ~TREXIO_END~ | 6 | 'End of file' | - | ~TREXIO_READONLY~ | 7 | 'Read-only file' | - | ~TREXIO_ERRNO~ | 8 | strerror(errno) | - | ~TREXIO_INVALID_ID~ | 9 | 'Invalid ID' | - | ~TREXIO_ALLOCATION_FAILED~ | 10 | 'Allocation failed' | - | ~TREXIO_HAS_NOT~ | 11 | 'Element absent' | - | ~TREXIO_INVALID_NUM~ | 12 | 'Invalid dimensions' | - | ~TREXIO_NUM_ALREADY_EXISTS~ | 13 | 'Variable already exists' | - | ~TREXIO_OPEN_ERROR~ | 14 | 'Error opening file' | - | ~TREXIO_LOCK_ERROR~ | 15 | 'Error locking file' | - | ~TREXIO_UNLOCK_ERROR~ | 16 | 'Error unlocking file' | - | ~TREXIO_FILE_ERROR~ | 17 | 'Invalid file handle' | - | ~TREXIO_GROUP_READ_ERROR~ | 18 | 'Error reading group' | - | ~TREXIO_GROUP_WRITE_ERROR~ | 19 | 'Error writing group' | - | ~TREXIO_ELEM_READ_ERROR~ | 20 | 'Error reading element' | - | ~TREXIO_ELEM_WRITE_ERROR~ | 21 | 'Error writing element' | + | Macro | Code | Description | + |------------------------------+------+----------------------------------------| + | ~TREXIO_FAILURE~ | -1 | 'Unknown failure' | + | ~TREXIO_SUCCESS~ | 0 | 'Success' | + | ~TREXIO_INVALID_ARG_1~ | 1 | 'Invalid argument 1' | + | ~TREXIO_INVALID_ARG_2~ | 2 | 'Invalid argument 2' | + | ~TREXIO_INVALID_ARG_3~ | 3 | 'Invalid argument 3' | + | ~TREXIO_INVALID_ARG_4~ | 4 | 'Invalid argument 4' | + | ~TREXIO_INVALID_ARG_5~ | 5 | 'Invalid argument 5' | + | ~TREXIO_END~ | 6 | 'End of file' | + | ~TREXIO_READONLY~ | 7 | 'Read-only file' | + | ~TREXIO_ERRNO~ | 8 | strerror(errno) | + | ~TREXIO_INVALID_ID~ | 9 | 'Invalid ID' | + | ~TREXIO_ALLOCATION_FAILED~ | 10 | 'Allocation failed' | + | ~TREXIO_HAS_NOT~ | 11 | 'Element absent' | + | ~TREXIO_INVALID_NUM~ | 12 | 'Invalid dimensions' | + | ~TREXIO_NUM_ALREADY_EXISTS~ | 13 | 'Dimensioning variable already exists' | + | ~TREXIO_DSET_ALREADY_EXISTS~ | 14 | 'Dataset already exists' | + | ~TREXIO_OPEN_ERROR~ | 15 | 'Error opening file' | + | ~TREXIO_LOCK_ERROR~ | 16 | 'Error locking file' | + | ~TREXIO_UNLOCK_ERROR~ | 17 | 'Error unlocking file' | + | ~TREXIO_FILE_ERROR~ | 18 | 'Invalid file handle' | + | ~TREXIO_GROUP_READ_ERROR~ | 19 | 'Error reading group' | + | ~TREXIO_GROUP_WRITE_ERROR~ | 20 | 'Error writing group' | + | ~TREXIO_ELEM_READ_ERROR~ | 21 | 'Error reading element' | + | ~TREXIO_ELEM_WRITE_ERROR~ | 22 | 'Error writing element' | # We need to force Emacs not to indent the Python code: # -*- org-src-preserve-indentation: t @@ -186,14 +187,15 @@ return '\n'.join(result) #define TREXIO_HAS_NOT ((trexio_exit_code) 11) #define TREXIO_INVALID_NUM ((trexio_exit_code) 12) #define TREXIO_NUM_ALREADY_EXISTS ((trexio_exit_code) 13) - #define TREXIO_OPEN_ERROR ((trexio_exit_code) 14) - #define TREXIO_LOCK_ERROR ((trexio_exit_code) 15) - #define TREXIO_UNLOCK_ERROR ((trexio_exit_code) 16) - #define TREXIO_FILE_ERROR ((trexio_exit_code) 17) - #define TREXIO_GROUP_READ_ERROR ((trexio_exit_code) 18) - #define TREXIO_GROUP_WRITE_ERROR ((trexio_exit_code) 19) - #define TREXIO_ELEM_READ_ERROR ((trexio_exit_code) 20) - #define TREXIO_ELEM_WRITE_ERROR ((trexio_exit_code) 21) + #define TREXIO_DSET_ALREADY_EXISTS ((trexio_exit_code) 14) + #define TREXIO_OPEN_ERROR ((trexio_exit_code) 15) + #define TREXIO_LOCK_ERROR ((trexio_exit_code) 16) + #define TREXIO_UNLOCK_ERROR ((trexio_exit_code) 17) + #define TREXIO_FILE_ERROR ((trexio_exit_code) 18) + #define TREXIO_GROUP_READ_ERROR ((trexio_exit_code) 19) + #define TREXIO_GROUP_WRITE_ERROR ((trexio_exit_code) 20) + #define TREXIO_ELEM_READ_ERROR ((trexio_exit_code) 21) + #define TREXIO_ELEM_WRITE_ERROR ((trexio_exit_code) 22) #+end_src #+begin_src f90 :tangle prefix_fortran.f90 :exports none @@ -212,14 +214,15 @@ return '\n'.join(result) integer(trexio_exit_code), parameter :: TREXIO_HAS_NOT = 11 integer(trexio_exit_code), parameter :: TREXIO_INVALID_NUM = 12 integer(trexio_exit_code), parameter :: TREXIO_NUM_ALREADY_EXISTS = 13 - integer(trexio_exit_code), parameter :: TREXIO_OPEN_ERROR = 14 - integer(trexio_exit_code), parameter :: TREXIO_LOCK_ERROR = 15 - integer(trexio_exit_code), parameter :: TREXIO_UNLOCK_ERROR = 16 - integer(trexio_exit_code), parameter :: TREXIO_FILE_ERROR = 17 - integer(trexio_exit_code), parameter :: TREXIO_GROUP_READ_ERROR = 18 - integer(trexio_exit_code), parameter :: TREXIO_GROUP_WRITE_ERROR = 19 - integer(trexio_exit_code), parameter :: TREXIO_ELEM_READ_ERROR = 20 - integer(trexio_exit_code), parameter :: TREXIO_ELEM_WRITE_ERROR = 21 + integer(trexio_exit_code), parameter :: TREXIO_DSET_ALREADY_EXISTS = 14 + integer(trexio_exit_code), parameter :: TREXIO_OPEN_ERROR = 15 + integer(trexio_exit_code), parameter :: TREXIO_LOCK_ERROR = 16 + integer(trexio_exit_code), parameter :: TREXIO_UNLOCK_ERROR = 17 + integer(trexio_exit_code), parameter :: TREXIO_FILE_ERROR = 18 + integer(trexio_exit_code), parameter :: TREXIO_GROUP_READ_ERROR = 19 + integer(trexio_exit_code), parameter :: TREXIO_GROUP_WRITE_ERROR = 20 + integer(trexio_exit_code), parameter :: TREXIO_ELEM_READ_ERROR = 21 + integer(trexio_exit_code), parameter :: TREXIO_ELEM_WRITE_ERROR = 22 #+end_src :end: @@ -448,7 +451,6 @@ struct trexio_back_end_s { 2) ~mode~ - character containing open mode (see below) - ~'w'~ - (write) creates a new file as READWRITE (overwrite existing file) - ~'r'~ - (read) opens existing file as READONLY - - ~'a'~ - (append) either opens file in READWRITE mode if it already exists or creates a new one 3) ~back_end~ - integer number (or the corresponding global parameter) specifying the back end - ~TREXIO_HDF5~ - for HDF5 back end (integer alternative: 0) - ~TREXIO_TEXT~ - for TEXT back end (integer alternative: 1) @@ -479,7 +481,7 @@ trexio_open(const char* file_name, const char mode, if (back_end < 0) return NULL; if (back_end >= TREXIO_INVALID_BACK_END) return NULL; - if (mode != 'r' && mode != 'w' && mode != 'a') return NULL; + if (mode != 'r' && mode != 'w') return NULL; trexio_t* result = NULL; void* result_tmp = NULL; @@ -844,6 +846,7 @@ trexio_write_$group_num$_64 (trexio_t* const file, const int64_t num) { if (file == NULL) return TREXIO_INVALID_ARG_1; if (num < 0 ) return TREXIO_INVALID_ARG_2; + if (trexio_has_$group_num$(file) == TREXIO_SUCCESS) return TREXIO_NUM_ALREADY_EXISTS; trexio_exit_code rc = TREXIO_GROUP_WRITE_ERROR; @@ -907,6 +910,7 @@ trexio_write_$group_num$_32 (trexio_t* const file, const int32_t num) if (file == NULL) return TREXIO_INVALID_ARG_1; if (num < 0 ) return TREXIO_INVALID_ARG_2; + if (trexio_has_$group_num$(file) == TREXIO_SUCCESS) return TREXIO_NUM_ALREADY_EXISTS; trexio_exit_code rc = TREXIO_GROUP_WRITE_ERROR; @@ -1130,6 +1134,7 @@ trexio_write_$group_dset$_64 (trexio_t* const file, const $group_dset_dtype_doub if (file == NULL) return TREXIO_INVALID_ARG_1; if ($group_dset$ == NULL) return TREXIO_INVALID_ARG_2; + if (trexio_has_$group_dset$(file) == TREXIO_SUCCESS) return TREXIO_DSET_ALREADY_EXISTS; trexio_exit_code rc; int64_t $group_dset_dim$ = 0; @@ -1231,6 +1236,7 @@ trexio_write_$group_dset$_32 (trexio_t* const file, const $group_dset_dtype_sing if (file == NULL) return TREXIO_INVALID_ARG_1; if ($group_dset$ == NULL) return TREXIO_INVALID_ARG_2; + if (trexio_has_$group_dset$(file) == TREXIO_SUCCESS) return TREXIO_DSET_ALREADY_EXISTS; trexio_exit_code rc; int64_t $group_dset_dim$ = 0; diff --git a/src/templates_hdf5/templator_hdf5.org b/src/templates_hdf5/templator_hdf5.org index 1954539..1f61684 100644 --- a/src/templates_hdf5/templator_hdf5.org +++ b/src/templates_hdf5/templator_hdf5.org @@ -97,13 +97,9 @@ trexio_hdf5_init (trexio_t* const file) // reading the existing file -> open as RDONLY f->file_id = H5Fopen(file->file_name, H5F_ACC_RDONLY, H5P_DEFAULT); break; - case 'a': - // appending the existing file -> open as RDWR - f->file_id = H5Fopen(file->file_name, H5F_ACC_RDWR, H5P_DEFAULT); - break; case 'w': - // writing the existing file -> overwrite it (_TRUNC) [_EXCL | H5F_ACC_DEBUG as an alternative] - f->file_id = H5Fcreate(file->file_name, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + // writing the existing file -> open as RDWRITE + f->file_id = H5Fopen(file->file_name, H5F_ACC_RDWR, H5P_DEFAULT); break; } @@ -111,8 +107,7 @@ trexio_hdf5_init (trexio_t* const file) switch (file->mode) { case 'r': - case 'a': - // reading or appending non-existing file -> error + // reading non-existing file -> error return TREXIO_FAILURE; case 'w': // writing non-existing file -> create it @@ -124,13 +119,15 @@ trexio_hdf5_init (trexio_t* const file) /* Create or open groups in the hdf5 file assuming that they exist if file exists */ switch (file->mode) { - // the switch for 'r'/'a' is reached only if file exists case 'r': - case 'a': f->$group$_group = H5Gopen(f->file_id, $GROUP$_GROUP_NAME, H5P_DEFAULT); break; case 'w': - f->$group$_group = H5Gcreate(f->file_id, $GROUP$_GROUP_NAME, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + if (f_exists == 1) { + f->$group$_group = H5Gopen(f->file_id, $GROUP$_GROUP_NAME, H5P_DEFAULT); + } else { + f->$group$_group = H5Gcreate(f->file_id, $GROUP$_GROUP_NAME, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + } break; } if (f->$group$_group <= 0L) return TREXIO_INVALID_ID; diff --git a/tests/test.c b/tests/test.c index 9fba6d9..ddb26d5 100644 --- a/tests/test.c +++ b/tests/test.c @@ -67,8 +67,6 @@ int test_write(const char* file_name, const back_end_t backend) { assert (rc == TREXIO_SUCCESS); rc = trexio_write_nucleus_coord(file,coord); assert (rc == TREXIO_SUCCESS); - rc = trexio_write_nucleus_charge(file,charge); - assert (rc == TREXIO_SUCCESS); // check if the written data exists in the file rc = trexio_has_nucleus_num(file); @@ -76,27 +74,26 @@ int test_write(const char* file_name, const back_end_t backend) { rc = trexio_has_nucleus_coord(file); assert (rc == TREXIO_SUCCESS); - // should not work: try to overwrite the nucleus_num + // should not work: try to overwrite the num variable rc = trexio_write_nucleus_num(file,25); printf("Test error message: %s\n", trexio_string_of_error(rc)); assert (rc == TREXIO_NUM_ALREADY_EXISTS); + // should not work: try to overwrite the dset + coord[0] = 666.666; + rc = trexio_write_nucleus_coord(file,coord); + assert (rc == TREXIO_DSET_ALREADY_EXISTS); + // close current session rc = trexio_close(file); assert (rc == TREXIO_SUCCESS); - // open file again in 'append' mode - file = trexio_open(file_name, 'a', TREXIO_HDF5); + // open file again in 'write' mode + file = trexio_open(file_name, 'w', backend); assert (file != NULL); - // read the nucleus_num from existing file - rc = trexio_read_nucleus_num(file,&num); - assert (rc == TREXIO_SUCCESS); - assert (num == 12); - - // overwrite the nucleus_coord - coord[0] = 666.666; - rc = trexio_write_nucleus_coord(file,coord); + // write some missing blocks (e.g. if forgot last time) + rc = trexio_write_nucleus_charge(file,charge); assert (rc == TREXIO_SUCCESS); // close current session @@ -148,12 +145,6 @@ int test_read(const char* file_name, const back_end_t backend) { file2 = trexio_open(file_name2, 'r', backend); assert (file2 == NULL); - // append non-existing file, should fail and return NULL - trexio_t* file3 = NULL; - - file3 = trexio_open(file_name2, 'a', backend); - assert (file3 == NULL); - /*================= END OF TEST =====================*/ free(coord);