1
0
mirror of https://github.com/TREX-CoE/trexio.git synced 2024-07-22 18:57:39 +02:00

Merge pull request #50 from TREX-CoE/add-strings

Add strings functionality
This commit is contained in:
Evgeny Posenitskiy 2021-06-15 12:11:25 +02:00 committed by GitHub
commit aac439803f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 1610 additions and 269 deletions

11
.gitignore vendored
View File

@ -12,6 +12,8 @@ config.log
config.status
config.sub
configure
config.h.in
config.h
depcomp
include/config.h.in
include/stamp-h1
@ -19,10 +21,15 @@ install-sh
libtool
ltmain.sh
ltximg/
Makefile
missing
Makefile
Makefile.in
pkgconfig/trexio.pc
test_write.h5
trexio.pc
trexio.mod
test-driver
test-suite.log
*.h5
trexio-*.tar.gz

View File

@ -91,7 +91,7 @@ $(test_trexio_f): $(trexio_f)
cp $(trexio_f) $(test_trexio_f)
clean-local:
-rm -rf -- test_write.dir/ test_write_f.dir/ test_write.h5
-rm -rf -- test_write.dir/ test_write_f.dir/ test_write.h5 test_write_f.h5
if TREXIO_DEVEL

View File

@ -21,7 +21,6 @@ AC_SUBST([VERSION_MINOR])
AC_SUBST([VERSION_PATCH])
## -------------------
## Checks for programs
## -------------------
@ -88,8 +87,7 @@ CPPFLAGS="${HDF5_CPPFLAGS} ${CPPFLAGS}"
LDFLAGS="${HDF5_LDFLAGS} ${LDFLAGS}"
LIBS="${HDF5_LIBS} ${LIBS}"
# Check if hdf5 if available with pkg-config
# Check if HDF5 if available with pkg-config
PKG_CHECK_MODULES([HDF5], [hdf5 >= 1.8], [
PKG_HDF5="hdf5"
@ -169,7 +167,8 @@ LDFLAGS .......: ${LDFLAGS}
LIBS ..........: ${LIBS}
Package features:
Compilation with HDF5: ${with_hdf5}
Compilation with HDF5...: ${with_hdf5}
HDF5 version............: ${HDF5_VERSION}
Now type 'make @<:@<target>@:>@'
where the optional <target> is:

1
src/.gitignore vendored
View File

@ -1,6 +1,7 @@
templates_front/*.c
templates_front/*.h
templates_front/*.f90
templates_front/*.fh_90
templates_front/*.dump
templates_front/populated/

View File

@ -12,6 +12,9 @@ cat populated/pop_*.h >> trexio.h
# fortran front end
cat populated/pop_*.f90 >> trexio_f.f90
# add helper functions
cat helper_fortran.f90 >> trexio_f.f90
cat populated/pop_*.fh_90 >> trexio_f.f90
# suffixes
cat suffix_s_front.h >> trexio_s.h

View File

@ -31,6 +31,8 @@ module trexio
integer(trexio_backend), parameter :: TREXIO_TEXT = 1
! integer(trexio_backend), parameter :: TREXIO_JSON = 2
integer(trexio_backend), parameter :: TREXIO_INVALID_BACK_END = 2
character(kind=c_char), parameter :: TREXIO_DELIM = c_new_line
#+end_src
#+end_src
@ -144,6 +146,7 @@ typedef int32_t trexio_exit_code;
| ~TREXIO_GROUP_WRITE_ERROR~ | 20 | 'Error writing group' |
| ~TREXIO_ELEM_READ_ERROR~ | 21 | 'Error reading element' |
| ~TREXIO_ELEM_WRITE_ERROR~ | 22 | 'Error writing element' |
| ~TREXIO_INVALID_STR_LEN~ | 30 | 'Invalid max_str_len' |
# We need to force Emacs not to indent the Python code:
# -*- org-src-preserve-indentation: t
@ -174,7 +177,7 @@ return '\n'.join(result)
#+RESULTS:
:results:
#+begin_src c :tangle prefix_front.h :exports none
#+begin_src c :tangle prefix_front.h
#define TREXIO_FAILURE ((trexio_exit_code) -1)
#define TREXIO_SUCCESS ((trexio_exit_code) 0)
#define TREXIO_INVALID_ARG_1 ((trexio_exit_code) 1)
@ -199,9 +202,10 @@ return '\n'.join(result)
#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)
#define TREXIO_INVALID_STR_LEN ((trexio_exit_code) 30)
#+end_src
#+begin_src f90 :tangle prefix_fortran.f90 :exports none
#+begin_src f90 :tangle prefix_fortran.f90
integer(trexio_exit_code), parameter :: TREXIO_FAILURE = -1
integer(trexio_exit_code), parameter :: TREXIO_SUCCESS = 0
integer(trexio_exit_code), parameter :: TREXIO_INVALID_ARG_1 = 1
@ -226,6 +230,7 @@ return '\n'.join(result)
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
integer(trexio_exit_code), parameter :: TREXIO_INVALID_STR_LEN = 30
#+end_src
:end:
@ -388,6 +393,8 @@ typedef int32_t back_end_t;
#define TREXIO_TEXT ( (back_end_t) 1 )
/*#define TREXIO_JSON ( (back_end_t) 2 )*/
#define TREXIO_INVALID_BACK_END ( (back_end_t) 2 )
#define TREXIO_DELIM "\n"
#+end_src
** Read/write behavior
@ -712,30 +719,8 @@ interface
end interface
#+end_src
** C helper functions
#+begin_src c :tangle prefix_front.c
trexio_exit_code transform_str (char** dest, const char** src, uint64_t str_max_num, uint32_t str_max_len){
if (dest == NULL) return TREXIO_INVALID_ARG_1;
assert (str_max_num > 0);
assert (str_max_len > 0);
char* tmp_str = (char*)calloc(str_max_num*(str_max_len+1)+1,sizeof(char));
for (int i=0; i<str_max_num; i++){
dest[i] = tmp_str;
strncpy(tmp_str, src[i], str_max_len);
tmp_str += str_max_len + 1;
}
/*tmp_str cannot be freed here but it is taken case of when pointer to dest is deallocated */
return TREXIO_SUCCESS;
}
#+end_src c
* Templates for front end
** Description
Consider the following block of =trex.json=:
@ -801,7 +786,7 @@ trexio_exit_code transform_str (char** dest, const char** src, uint64_t str_max_
*read* and *write* functionality. TREXIO supports I/O with single
or double precision for integer and floating point numbers.
** Templates for front end has/read/write a dimension
** Templates for front end has/read/write a single dimensioning variable
This section concerns API calls related to dimensioning variables.
@ -877,26 +862,23 @@ trexio_write_$group_num$_64 (trexio_t* const file, const int64_t num)
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;
switch (file->back_end) {
case TREXIO_TEXT:
rc = trexio_text_write_$group_num$(file, (int64_t) num);
return trexio_text_write_$group_num$(file, (int64_t) num);
break;
case TREXIO_HDF5:
rc = trexio_hdf5_write_$group_num$(file, (int64_t) num);
return trexio_hdf5_write_$group_num$(file, (int64_t) num);
break;
/*
case TREXIO_JSON:
rc = trexio_json_write_$group_num$(file, (int64_t) num);
return trexio_json_write_$group_num$(file, (int64_t) num);
break;
,*/
}
if (rc != TREXIO_SUCCESS) return rc;
return TREXIO_SUCCESS;
return TREXIO_FAILURE;
}
#+end_src
@ -941,26 +923,23 @@ trexio_write_$group_num$_32 (trexio_t* const file, const int32_t num)
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;
switch (file->back_end) {
case TREXIO_TEXT:
rc = trexio_text_write_$group_num$(file, (int64_t) num);
return trexio_text_write_$group_num$(file, (int64_t) num);
break;
case TREXIO_HDF5:
rc = trexio_hdf5_write_$group_num$(file, (int64_t) num);
return trexio_hdf5_write_$group_num$(file, (int64_t) num);
break;
/*
case TREXIO_JSON:
rc = trexio_json_write_$group_num$(file, (int64_t) num);
return trexio_json_write_$group_num$(file, (int64_t) num);
break;
,*/
}
if (rc != TREXIO_SUCCESS) return rc;
return TREXIO_SUCCESS;
return TREXIO_FAILURE;
}
#+end_src
@ -1004,8 +983,8 @@ trexio_has_$group_num$ (trexio_t* const file)
break;
,*/
}
return TREXIO_FAILURE;
return TREXIO_FAILURE;
}
#+end_src
@ -1083,7 +1062,7 @@ interface
end interface
#+end_src
** Templates for front end has/read/write a dataset
** Templates for front end has/read/write a dataset of numerical data
This section concerns API calls related to datasets.
@ -1106,7 +1085,7 @@ end interface
The basic (non-suffixed) API call on datasets deals with double precision (see Table above).
#+begin_src c :tangle hrw_dset_front.h :exports none
#+begin_src c :tangle hrw_dset_data_front.h :exports none
trexio_exit_code trexio_has_$group_dset$(trexio_t* const file);
trexio_exit_code trexio_read_$group_dset$(trexio_t* const file, $group_dset_dtype_default$* const $group_dset$);
trexio_exit_code trexio_write_$group_dset$(trexio_t* const file, const $group_dset_dtype_default$* $group_dset$);
@ -1116,7 +1095,7 @@ trexio_exit_code trexio_read_$group_dset$_64(trexio_t* const file, $group_dset_d
trexio_exit_code trexio_write_$group_dset$_64(trexio_t* const file, const $group_dset_dtype_double$* $group_dset$);
#+end_src
#+begin_src c :tangle read_dset_64_front.c
#+begin_src c :tangle read_dset_data_64_front.c
trexio_exit_code
trexio_read_$group_dset$_64 (trexio_t* const file, $group_dset_dtype_double$* const $group_dset$)
{
@ -1171,7 +1150,7 @@ trexio_read_$group_dset$_64 (trexio_t* const file, $group_dset_dtype_double$* co
}
#+end_src
#+begin_src c :tangle write_dset_64_front.c
#+begin_src c :tangle write_dset_data_64_front.c
trexio_exit_code
trexio_write_$group_dset$_64 (trexio_t* const file, const $group_dset_dtype_double$* $group_dset$)
{
@ -1192,7 +1171,7 @@ trexio_write_$group_dset$_64 (trexio_t* const file, const $group_dset_dtype_doub
uint32_t rank = $group_dset_rank$;
uint64_t dims[$group_dset_rank$] = {$group_dset_dim_list$};
$group_dset_dtype_double$* $group_dset$_p = $group_dset$;
$group_dset_dtype_double$* $group_dset$_p = ($group_dset_dtype_double$*) $group_dset$;
/* Handle index type */
if ($is_index$) {
@ -1238,7 +1217,7 @@ trexio_write_$group_dset$_64 (trexio_t* const file, const $group_dset_dtype_doub
}
#+end_src
#+begin_src c :tangle read_dset_32_front.c
#+begin_src c :tangle read_dset_data_32_front.c
trexio_exit_code
trexio_read_$group_dset$_32 (trexio_t* const file, $group_dset_dtype_single$* const $group_dset$)
{
@ -1305,7 +1284,7 @@ trexio_read_$group_dset$_32 (trexio_t* const file, $group_dset_dtype_single$* co
}
#+end_src
#+begin_src c :tangle write_dset_32_front.c
#+begin_src c :tangle write_dset_data_32_front.c
trexio_exit_code
trexio_write_$group_dset$_32 (trexio_t* const file, const $group_dset_dtype_single$* $group_dset$)
{
@ -1371,7 +1350,7 @@ trexio_write_$group_dset$_32 (trexio_t* const file, const $group_dset_dtype_sing
}
#+end_src
#+begin_src c :tangle read_dset_def_front.c
#+begin_src c :tangle read_dset_data_def_front.c
trexio_exit_code
trexio_read_$group_dset$ (trexio_t* const file, $group_dset_dtype_default$* const $group_dset$)
{
@ -1379,7 +1358,7 @@ trexio_read_$group_dset$ (trexio_t* const file, $group_dset_dtype_default$* cons
}
#+end_src
#+begin_src c :tangle write_dset_def_front.c
#+begin_src c :tangle write_dset_data_def_front.c
trexio_exit_code
trexio_write_$group_dset$ (trexio_t* const file, const $group_dset_dtype_default$* $group_dset$)
{
@ -1387,7 +1366,7 @@ trexio_write_$group_dset$ (trexio_t* const file, const $group_dset_dtype_default
}
#+end_src
#+begin_src c :tangle has_dset_front.c
#+begin_src c :tangle has_dset_data_front.c
trexio_exit_code
trexio_has_$group_dset$ (trexio_t* const file)
{
@ -1420,7 +1399,7 @@ trexio_has_$group_dset$ (trexio_t* const file)
The ~Fortran~ templates that provide an access to the ~C~ API calls from ~Fortran~.
These templates are based on the use of ~iso_c_binding~. Pointers have to be passed by value.
#+begin_src f90 :tangle write_dset_64_front_fortran.f90
#+begin_src f90 :tangle write_dset_data_64_front_fortran.f90
interface
integer function trexio_write_$group_dset$_64 (trex_file, dset) bind(C)
use, intrinsic :: iso_c_binding
@ -1430,7 +1409,7 @@ interface
end interface
#+end_src
#+begin_src f90 :tangle read_dset_64_front_fortran.f90
#+begin_src f90 :tangle read_dset_data_64_front_fortran.f90
interface
integer function trexio_read_$group_dset$_64 (trex_file, dset) bind(C)
use, intrinsic :: iso_c_binding
@ -1440,7 +1419,7 @@ interface
end interface
#+end_src
#+begin_src f90 :tangle write_dset_32_front_fortran.f90
#+begin_src f90 :tangle write_dset_data_32_front_fortran.f90
interface
integer function trexio_write_$group_dset$_32 (trex_file, dset) bind(C)
use, intrinsic :: iso_c_binding
@ -1450,7 +1429,7 @@ interface
end interface
#+end_src
#+begin_src f90 :tangle read_dset_32_front_fortran.f90
#+begin_src f90 :tangle read_dset_data_32_front_fortran.f90
interface
integer function trexio_read_$group_dset$_32 (trex_file, dset) bind(C)
use, intrinsic :: iso_c_binding
@ -1460,7 +1439,7 @@ interface
end interface
#+end_src
#+begin_src f90 :tangle write_dset_def_front_fortran.f90
#+begin_src f90 :tangle write_dset_data_def_front_fortran.f90
interface
integer function trexio_write_$group_dset$ (trex_file, dset) bind(C)
use, intrinsic :: iso_c_binding
@ -1470,7 +1449,7 @@ interface
end interface
#+end_src
#+begin_src f90 :tangle read_dset_def_front_fortran.f90
#+begin_src f90 :tangle read_dset_data_def_front_fortran.f90
interface
integer function trexio_read_$group_dset$ (trex_file, dset) bind(C)
use, intrinsic :: iso_c_binding
@ -1480,7 +1459,7 @@ interface
end interface
#+end_src
#+begin_src f90 :tangle has_dset_front_fortran.f90
#+begin_src f90 :tangle has_dset_data_front_fortran.f90
interface
integer function trexio_has_$group_dset$ (trex_file) bind(C)
use, intrinsic :: iso_c_binding
@ -1603,6 +1582,524 @@ trexio_read_chunk_ao_2e_int_eri_value_64(trexio_t* const file,
}
#+END_SRC
** Templates for front end has/read/write a dataset of strings
*** Introduction
This section concerns API calls related to datasets of strings.
| Function name | Description |
|-----------------------------+-------------------------------------|
| ~trexio_has_$group_dset$~ | Check if a dataset exists in a file |
| ~trexio_read_$group_dset$~ | Read a dataset |
| ~trexio_write_$group_dset$~ | Write a dataset |
*** C templates for front end
First parameter is the ~TREXIO~ file handle. Second parameter is the variable to be written/read
to/from the ~TREXIO~ file (except for ~trexio_has_~ functions).
#+begin_src c :tangle hrw_dset_str_front.h :exports none
trexio_exit_code trexio_has_$group_dset$(trexio_t* const file);
trexio_exit_code trexio_read_$group_dset$_low(trexio_t* const file, char* dset, const uint32_t max_str_len);
trexio_exit_code trexio_write_$group_dset$_low(trexio_t* const file, const char* dset, const uint32_t max_str_len);
trexio_exit_code trexio_read_$group_dset$(trexio_t* const file, char** dset, const uint32_t max_str_len);
trexio_exit_code trexio_write_$group_dset$(trexio_t* const file, const char** dset, const uint32_t max_str_len);
#+end_src
#+begin_src c :tangle read_dset_str_front.c
trexio_exit_code
trexio_read_$group_dset$_low (trexio_t* const file, char* dset, const uint32_t max_str_len)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
if (dset == NULL) return TREXIO_INVALID_ARG_2;
if (max_str_len <= 0) return TREXIO_INVALID_ARG_3;
trexio_exit_code rc;
int64_t $group_dset_dim$ = 0;
/* Error handling for this call is added by the generator */
rc = trexio_read_$group_dset_dim$_64(file, &($group_dset_dim$));
if ($group_dset_dim$ == 0L) return TREXIO_INVALID_NUM;
uint32_t rank = $group_dset_rank$;
uint64_t dims[$group_dset_rank$] = {$group_dset_dim_list$};
assert(file->back_end < TREXIO_INVALID_BACK_END);
switch (file->back_end) {
case TREXIO_TEXT:
return trexio_text_read_$group_dset$(file, dset, rank, dims, max_str_len);
break;
case TREXIO_HDF5:
return trexio_hdf5_read_$group_dset$(file, dset, rank, dims, max_str_len);
break;
/*
case TREXIO_JSON:
rc = trexio_json_read_$group_dset$(file, dset, rank, dims);
break;
,*/
}
}
trexio_exit_code
trexio_read_$group_dset$ (trexio_t* const file, char** dset, const uint32_t max_str_len)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
if (dset == NULL) return TREXIO_INVALID_ARG_2;
if (max_str_len <= 0) return TREXIO_INVALID_ARG_3;
assert(file->back_end < TREXIO_INVALID_BACK_END);
trexio_exit_code rc;
int64_t dset_dim = 0;
/* Error handling for this call is added by the generator */
rc = trexio_read_$group_dset_dim$_64(file, &(dset_dim));
if (dset_dim == 0L) return TREXIO_INVALID_NUM;
char* str_compiled = CALLOC(dset_dim*(max_str_len+1) + 1, char);
if (str_compiled == NULL) return TREXIO_ALLOCATION_FAILED;
rc = trexio_read_$group_dset$_low(file, str_compiled, max_str_len);
if (rc != TREXIO_SUCCESS) {
FREE(str_compiled);
return rc;
}
char * pch;
for (uint64_t i=0; i < dset_dim; i++) {
pch = i == 0 ? strtok(str_compiled, TREXIO_DELIM) : strtok(NULL, TREXIO_DELIM) ;
if (pch == NULL) {
FREE(str_compiled);
return TREXIO_FAILURE;
}
strcpy(dset[i], "");
strcat(dset[i], pch);
}
FREE(str_compiled);
return TREXIO_SUCCESS;
}
#+end_src
#+begin_src c :tangle write_dset_str_front.c
trexio_exit_code
trexio_write_$group_dset$_low (trexio_t* const file, const char* dset, const uint32_t max_str_len)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
if (dset == NULL) return TREXIO_INVALID_ARG_2;
if (max_str_len <= 0) return TREXIO_INVALID_ARG_3;
if (trexio_has_$group_dset$(file) == TREXIO_SUCCESS) return TREXIO_DSET_ALREADY_EXISTS;
trexio_exit_code rc;
int64_t $group_dset_dim$ = 0;
/* Error handling for this call is added by the generator */
rc = trexio_read_$group_dset_dim$_64(file, &($group_dset_dim$));
if ($group_dset_dim$ == 0L) return TREXIO_INVALID_NUM;
uint32_t rank = $group_dset_rank$;
uint64_t dims[$group_dset_rank$] = {$group_dset_dim_list$};
assert(file->back_end < TREXIO_INVALID_BACK_END);
char* tmp_str = CALLOC(dims[0]*(max_str_len+1), char);
if (tmp_str == NULL) return TREXIO_ALLOCATION_FAILED;
char** dset_str = CALLOC(dims[0], char*);
if (dset_str == NULL) return TREXIO_ALLOCATION_FAILED;
char* pch;
size_t pch_len;
/* parse the string using strtok */
for(uint64_t i=0; i<dims[0]; i++) {
pch = i == 0 ? strtok( (char*) dset, TREXIO_DELIM) : strtok(NULL, TREXIO_DELIM) ;
if (pch == NULL) {
FREE(dset_str[0]);
FREE(dset_str);
return TREXIO_FAILURE;
}
pch_len = strlen(pch);
if (pch_len > max_str_len) {
FREE(dset_str[0]);
FREE(dset_str);
return TREXIO_INVALID_STR_LEN;
}
dset_str[i] = tmp_str;
strncpy(tmp_str, pch, pch_len);
tmp_str += pch_len + 1;
}
rc = TREXIO_FAILURE;
switch (file->back_end) {
case TREXIO_TEXT:
rc = trexio_text_write_$group_dset$(file, (const char**) dset_str, rank, dims);
break;
case TREXIO_HDF5:
rc = trexio_hdf5_write_$group_dset$(file, (const char**) dset_str, rank, dims);
break;
/*
case TREXIO_JSON:
rc = trexio_json_write_$group_dset$(file, dset, rank, dims);
break;
,*/
}
FREE(dset_str[0]);
FREE(dset_str);
return rc;
}
trexio_exit_code
trexio_write_$group_dset$ (trexio_t* const file, const char** dset, const uint32_t max_str_len)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
if (dset == NULL) return TREXIO_INVALID_ARG_2;
if (max_str_len <= 0) return TREXIO_INVALID_ARG_3;
if (trexio_has_$group_dset$(file) == TREXIO_SUCCESS) return TREXIO_DSET_ALREADY_EXISTS;
assert(file->back_end < TREXIO_INVALID_BACK_END);
trexio_exit_code rc;
int64_t dset_dim = 0;
/* Error handling for this call is added by the generator */
rc = trexio_read_$group_dset_dim$_64(file, &(dset_dim));
if (dset_dim == 0L) return TREXIO_INVALID_NUM;
char* str_compiled = CALLOC(dset_dim*max_str_len + 1, char);
if (str_compiled == NULL) return TREXIO_ALLOCATION_FAILED;
strcpy(str_compiled, "");
for (uint64_t i=0; i < dset_dim; i++) {
strcat(str_compiled, dset[i]);
strcat(str_compiled, TREXIO_DELIM);
}
rc = trexio_write_$group_dset$_low(file, str_compiled, max_str_len);
FREE(str_compiled);
return rc;
}
#+end_src
#+begin_src c :tangle has_dset_str_front.c
trexio_exit_code
trexio_has_$group_dset$ (trexio_t* const file)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
assert(file->back_end < TREXIO_INVALID_BACK_END);
switch (file->back_end) {
case TREXIO_TEXT:
return trexio_text_has_$group_dset$(file);
break;
case TREXIO_HDF5:
return trexio_hdf5_has_$group_dset$(file);
break;
/*
case TREXIO_JSON:
return trexio_json_has_$group_dset$(file);
break;
,*/
}
return TREXIO_FAILURE;
}
#+end_src
*** Fortran templates for front end
The ~Fortran~ templates that provide an access to the ~C~ API calls from ~Fortran~.
These templates are based on the use of ~iso_c_binding~. Pointers have to be passed by value.
#+begin_src f90 :tangle write_dset_str_front_fortran.f90
interface
integer function trexio_write_$group_dset$_low (trex_file, dset, max_str_len) bind(C)
use, intrinsic :: iso_c_binding
integer(8), intent(in), value :: trex_file
character, intent(in) :: dset(*)
integer(4), intent(in), value :: max_str_len
end function trexio_write_$group_dset$_low
end interface
#+end_src
#+begin_src f90 :tangle read_dset_str_front_fortran.f90
interface
integer function trexio_read_$group_dset$_low (trex_file, dset, max_str_len) bind(C)
use, intrinsic :: iso_c_binding
integer(8), intent(in), value :: trex_file
character, intent(out) :: dset(*)
integer(4), intent(in), value :: max_str_len
end function trexio_read_$group_dset$_low
end interface
#+end_src
#+begin_src f90 :tangle has_dset_str_front_fortran.f90
interface
integer function trexio_has_$group_dset$ (trex_file) bind(C)
use, intrinsic :: iso_c_binding
integer(8), intent(in), value :: trex_file
end function trexio_has_$group_dset$
end interface
#+end_src
#+begin_src f90 :tangle helper_read_dset_str_front_fortran.fh_90
integer function trexio_read_$group_dset$ (trex_file, dset, max_str_len)
implicit none
integer(8), intent(in), value :: trex_file
integer(4), intent(in), value :: max_str_len
character(len=*), intent(inout) :: dset(*)
character, allocatable :: str_compiled(:)
integer(8) :: $group_dset_dim$
integer :: rc
rc = trexio_read_$group_dset_dim$_64(trex_file, $group_dset_dim$)
if (rc /= TREXIO_SUCCESS) trexio_read_$group_dset$ = rc
allocate(str_compiled($group_dset_dim$*(max_str_len+1)+1))
rc = trexio_read_$group_dset$_low(trex_file, str_compiled, max_str_len)
if (rc /= TREXIO_SUCCESS) then
deallocate(str_compiled)
trexio_read_$group_dset$ = rc
else
call trexio_str2strarray(str_compiled, $group_dset_dim$, max_str_len, dset)
deallocate(str_compiled)
trexio_read_$group_dset$ = TREXIO_SUCCESS
endif
end function trexio_read_$group_dset$
#+end_src
#+begin_src f90 :tangle helper_write_dset_str_front_fortran.fh_90
integer function trexio_write_$group_dset$ (trex_file, dset, max_str_len)
implicit none
integer(8), intent(in), value :: trex_file
integer(4), intent(in), value :: max_str_len
character(len=*), intent(in) :: dset(*)
character(len=:), allocatable :: str_compiled
integer(8) :: $group_dset_dim$
integer :: rc
rc = trexio_read_$group_dset_dim$_64(trex_file, $group_dset_dim$)
if (rc /= TREXIO_SUCCESS) then
trexio_write_$group_dset$ = rc
else
call trexio_strarray2str(dset, $group_dset_dim$, max_str_len, str_compiled)
trexio_write_$group_dset$ = trexio_write_$group_dset$_low(trex_file, str_compiled, max_str_len)
endif
end function trexio_write_$group_dset$
#+end_src
** Templates for front end has/read/write a single string attribute
*** Introduction
This section concerns API calls related to string attributes.
| Function name | Description |
|----------------------------+----------------------------------------------|
| ~trexio_has_$group_str$~ | Check if a string attribute exists in a file |
| ~trexio_read_$group_str$~ | Read a string attribute |
| ~trexio_write_$group_str$~ | Write a string attribute |
*** C templates for front end
#+begin_src c :tangle hrw_attr_str_front.h :exports none
trexio_exit_code trexio_has_$group_str$(trexio_t* const file);
trexio_exit_code trexio_read_$group_str$(trexio_t* const file, char* const str, const uint32_t max_str_len);
trexio_exit_code trexio_write_$group_str$(trexio_t* const file, const char* str, const uint32_t max_str_len);
#+end_src
#+begin_src c :tangle read_attr_str_front.c
trexio_exit_code
trexio_read_$group_str$ (trexio_t* const file, char* const str, const uint32_t max_str_len)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
if (str == NULL) return TREXIO_INVALID_ARG_2;
if (max_str_len <= 0) return TREXIO_INVALID_ARG_3;
trexio_exit_code rc = TREXIO_FAILURE;
switch (file->back_end) {
case TREXIO_TEXT:
return trexio_text_read_$group_str$(file, str, max_str_len);
break;
case TREXIO_HDF5:
return trexio_hdf5_read_$group_str$(file, str, max_str_len);
break;
/*
case TREXIO_JSON:
return trexio_json_read_$group_str$(file, str);
break;
,*/
}
}
#+end_src
#+begin_src c :tangle write_attr_str_front.c
trexio_exit_code
trexio_write_$group_str$ (trexio_t* const file, const char* str, const uint32_t max_str_len)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
if (str == NULL) return TREXIO_INVALID_ARG_2;
if (max_str_len <= 0) return TREXIO_INVALID_ARG_3;
if (trexio_has_$group_str$(file) == TREXIO_SUCCESS) return TREXIO_NUM_ALREADY_EXISTS;
size_t len_write = strlen(str);
if (max_str_len < len_write) return TREXIO_INVALID_STR_LEN;
switch (file->back_end) {
case TREXIO_TEXT:
return trexio_text_write_$group_str$(file, str);
break;
case TREXIO_HDF5:
return trexio_hdf5_write_$group_str$(file, str);
break;
/*
case TREXIO_JSON:
return trexio_json_write_$group_str$(file, str);
break;
,*/
}
}
#+end_src
#+begin_src c :tangle has_attr_str_front.c
trexio_exit_code
trexio_has_$group_str$ (trexio_t* const file)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
assert(file->back_end < TREXIO_INVALID_BACK_END);
switch (file->back_end) {
case TREXIO_TEXT:
return trexio_text_has_$group_str$(file);
break;
case TREXIO_HDF5:
return trexio_hdf5_has_$group_str$(file);
break;
/*
case TREXIO_JSON:
return trexio_json_has_$group_str$(file);
break;
,*/
}
return TREXIO_FAILURE;
}
#+end_src
*** Fortran templates for front end
The ~Fortran~ templates that provide an access to the ~C~ API calls from Fortran.
These templates are based on the use of ~iso_c_binding~. Pointers have to be passed by value.
#+begin_src f90 :tangle write_attr_str_front_fortran.f90
interface
integer function trexio_write_$group_str$_c (trex_file, str, max_str_len) &
bind(C, name="trexio_write_$group_str$")
use, intrinsic :: iso_c_binding
integer(8), intent(in), value :: trex_file
character, intent(in) :: str(*)
integer(4), intent(in), value :: max_str_len
end function trexio_write_$group_str$_c
end interface
#+end_src
#+begin_src f90 :tangle read_attr_str_front_fortran.f90
interface
integer function trexio_read_$group_str$_c (trex_file, str, max_str_len) &
bind(C, name="trexio_read_$group_str$")
use, intrinsic :: iso_c_binding
integer(8), intent(in), value :: trex_file
character, intent(out) :: str(*)
integer(4), intent(in), value :: max_str_len
end function trexio_read_$group_str$_c
end interface
#+end_src
#+begin_src f90 :tangle has_attr_str_front_fortran.f90
interface
integer function trexio_has_$group_str$ (trex_file) bind(C)
use, intrinsic :: iso_c_binding
integer(8), intent(in), value :: trex_file
end function trexio_has_$group_str$
end interface
#+end_src
#+begin_src f90 :tangle helper_read_attr_str_front_fortran.fh_90
integer function trexio_read_$group_str$ (trex_file, str, max_str_len)
implicit none
integer(8), intent(in), value :: trex_file
integer(4), intent(in), value :: max_str_len
character, intent(out) :: str(*)
trexio_read_$group_str$ = trexio_read_$group_str$_c(trex_file, str, max_str_len)
end function trexio_read_$group_str$
#+end_src
#+begin_src f90 :tangle helper_write_attr_str_front_fortran.fh_90
integer function trexio_write_$group_str$ (trex_file, str, max_str_len)
use, intrinsic :: iso_c_binding, only : c_null_char
implicit none
integer(8), intent(in), value :: trex_file
integer(4), intent(in), value :: max_str_len
character(len=*), intent(in) :: str
character(len=len_trim(str)+1) :: str_c
str_c = trim(str) // c_null_char
trexio_write_$group_str$ = trexio_write_$group_str$_c(trex_file, str_c, max_str_len)
end function trexio_write_$group_str$
#+end_src
* Fortran helper/wrapper functions
The function below adapts the original C-based ~trexio_open~ for Fortran.
@ -1610,12 +2107,12 @@ trexio_read_chunk_ao_2e_int_eri_value_64(trexio_t* const file,
unlike strings in Fortran.
Note, that Fortran interface calls the main ~TREXIO~ API, which is written in C.
#+begin_src f90 :tangle suffix_fortran.f90
#+begin_src f90 :tangle helper_fortran.f90
contains
integer(8) function trexio_open (filename, mode, backend)
use, intrinsic :: iso_c_binding
use, intrinsic :: iso_c_binding, only : c_null_char
implicit none
character(len=*) :: filename
character(len=*), intent(in) :: filename
character, intent(in), value :: mode
integer(trexio_backend), intent(in), value :: backend
character(len=len_trim(filename)+1) :: filename_c
@ -1634,6 +2131,93 @@ contains
end function trexio_open
#+end_src
The subroutine below transforms an array of Fortran strings into one big string using ~TREXIO_DELIM~ symbol
as a delimeter and adds ~NULL~ character in the end in order to properly pass the desired string to
C API. This is needed due to the fact that strings in C are terminated by ~NULL~ character ~\0~.
#+begin_src f90 :tangle helper_fortran.f90
subroutine trexio_strarray2str(str_array, max_num_str, max_len_str, str_res)
use, intrinsic :: iso_c_binding, only : c_null_char
implicit none
integer(8), intent(in), value :: max_num_str ! number of elements in strign array
integer, intent(in), value :: max_len_str ! maximum length of a string in an array
character(len=*), intent(in) :: str_array(*)
character(len=:), allocatable, intent(out) :: str_res
integer :: i
str_res = ''
do i = 1, max_num_str
str_res = str_res // trim(str_array(i)) // TREXIO_DELIM
enddo
str_res = str_res // c_null_char
end subroutine trexio_strarray2str
#+end_src
The subroutine below does the reverse tranformation from one big string with delimeters into an array of Fortran strings.
#+begin_src f90 :tangle helper_fortran.f90
subroutine trexio_str2strarray(str_flat, max_num_str, max_len_str, str_array)
implicit none
integer(8), intent(in), value :: max_num_str ! number of elements in strign array
integer, intent(in), value :: max_len_str ! maximum length of a string in an array
character, intent(in) :: str_flat(*)
character(len=*), intent(inout) :: str_array(*)
character(len=max_len_str) :: tmp_str
integer :: i, j, k, ind, offset
integer(8) :: len_flat
len_flat = (max_len_str+1)*max_num_str + 1
ind=1
offset=1
do i=1,max_num_str
k = 1
tmp_str=''
do j=ind,len_flat
if (str_flat(j) == TREXIO_DELIM) then
ind=j+1
exit
endif
tmp_str(k:k) = str_flat(j)
k = k + 1
enddo
str_array(i)=tmp_str
offset=ind
enddo
end subroutine trexio_str2strarray
#+end_src
The subroutine is a Fortran analogue of ~assert~ in C. It check that the the return code of the
TREXIO API call is equal to a given return code. It can optionally print a success message if the
two code are identical, i.e. if the ~assert~ statement pass.
#+begin_src f90 :tangle helper_fortran.f90
subroutine trexio_assert(trexio_rc, check_rc, success_message)
implicit none
integer, intent(in), value :: trexio_rc
integer, intent(in), value :: check_rc
character(len=*), intent(in), optional :: success_message
character*(128) :: str
if (trexio_rc == check_rc) then
if (present(success_message)) write(*,*) success_message
else
call trexio_string_of_error(trexio_rc, str)
print *, trim(str)
call exit(1)
endif
end subroutine trexio_assert
#+end_src
* File suffixes :noexport:
#+begin_src c :tangle suffix_front.h

View File

@ -7,14 +7,10 @@ cat populated/pop_def_hdf5.c >> trexio_hdf5.c
cat populated/pop_struct_hdf5.h >> trexio_hdf5.h
cat populated/pop_basic_hdf5.c >> trexio_hdf5.c
cat populated/pop_has_dset_hdf5.c >> trexio_hdf5.c
cat populated/pop_has_num_hdf5.c >> trexio_hdf5.c
cat populated/pop_read_dset_hdf5.c >> trexio_hdf5.c
cat populated/pop_read_num_hdf5.c >> trexio_hdf5.c
cat populated/pop_write_dset_hdf5.c >> trexio_hdf5.c
cat populated/pop_write_num_hdf5.c >> trexio_hdf5.c
cat populated/pop_hrw_num_hdf5.h >> trexio_hdf5.h
cat populated/pop_hrw_dset_hdf5.h >> trexio_hdf5.h
cat populated/pop_has_*.c >> trexio_hdf5.c
cat populated/pop_read_*.c >> trexio_hdf5.c
cat populated/pop_write_*.c >> trexio_hdf5.c
cat populated/pop_hrw_*.h >> trexio_hdf5.h
cat suffix_hdf5.h >> trexio_hdf5.h

View File

@ -39,7 +39,7 @@
#include <sys/stat.h>
#include "hdf5.h"
#include "hdf5_hl.h" // needed for high-level APIs like H5LT, requires additional linking in Makefile
#include "hdf5_hl.h"
#+end_src
@ -56,6 +56,7 @@
#define $GROUP$_GROUP_NAME "$group$"
#define $GROUP_NUM$_NAME "$group_num$"
#define $GROUP_DSET$_NAME "$group_dset$"
#define $GROUP_STR$_NAME "$group_str$"
#+end_src
** Template for HDF5 structures
@ -152,7 +153,7 @@ trexio_hdf5_deinit (trexio_t* const file)
}
#+end_src
** Template for HDF5 has/read/write a number
** Template for HDF5 has/read/write a single dimensioning variable
#+begin_src c :tangle hrw_num_hdf5.h :exports none
trexio_exit_code trexio_hdf5_has_$group_num$ (trexio_t* const file);
@ -173,11 +174,14 @@ trexio_hdf5_read_$group_num$ (trexio_t* const file, uint64_t* const num)
/* Quit if the dimensioning attribute is missing in the file */
if (H5Aexists(f->$group$_group, $GROUP_NUM$_NAME) == 0) return TREXIO_FAILURE;
/* Read the nucleus_num attribute of nucleus group */
/* Read the $group_num$ attribute of $group$ group */
const hid_t num_id = H5Aopen(f->$group$_group, $GROUP_NUM$_NAME, H5P_DEFAULT);
if (num_id <= 0) return TREXIO_INVALID_ID;
const herr_t status = H5Aread(num_id, H5T_NATIVE_UINT64, num);
H5Aclose(num_id);
if (status < 0) return TREXIO_FAILURE;
return TREXIO_SUCCESS;
@ -276,18 +280,17 @@ trexio_hdf5_has_$group_num$ (trexio_t* const file)
}
#+end_src
** Template for HDF5 has/read/write a dataset
** Template for HDF5 has/read/write a dataset of numerical data
#+begin_src c :tangle hrw_dset_hdf5.h :exports none
#+begin_src c :tangle hrw_dset_data_hdf5.h :exports none
trexio_exit_code trexio_hdf5_has_$group_dset$(trexio_t* const file);
trexio_exit_code trexio_hdf5_read_$group_dset$(trexio_t* const file, $group_dset_dtype$* const $group_dset$, const uint32_t rank, const uint64_t* dims);
trexio_exit_code trexio_hdf5_write_$group_dset$(trexio_t* const file, const $group_dset_dtype$* $group_dset$, const uint32_t rank, const uint64_t* dims);
#+end_src
#+begin_src c :tangle read_dset_hdf5.c
#+begin_src c :tangle read_dset_data_hdf5.c
trexio_exit_code
trexio_hdf5_read_$group_dset$ (trexio_t* const file, $group_dset_dtype$* const $group_dset$,
const uint32_t rank, const uint64_t* dims)
trexio_hdf5_read_$group_dset$ (trexio_t* const file, $group_dset_dtype$* const $group_dset$, const uint32_t rank, const uint64_t* dims)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
@ -317,17 +320,17 @@ trexio_hdf5_read_$group_dset$ (trexio_t* const file, $group_dset_dtype$* const $
H5Dclose(dset_id);
if (status < 0) {
free(ddims);
FREE(ddims);
return TREXIO_FAILURE;
}
for (uint32_t i=0; i<rank; ++i){
if (ddims[i] != dims[i]) {
free(ddims);
FREE(ddims);
return TREXIO_INVALID_ARG_4;
}
}
free(ddims);
FREE(ddims);
/* High-level H5LT API. No need to deal with dataspaces and datatypes */
status = H5LTread_dataset(f->$group$_group,
@ -340,10 +343,9 @@ trexio_hdf5_read_$group_dset$ (trexio_t* const file, $group_dset_dtype$* const $
}
#+end_src
#+begin_src c :tangle write_dset_hdf5.c
#+begin_src c :tangle write_dset_data_hdf5.c
trexio_exit_code
trexio_hdf5_write_$group_dset$ (trexio_t* const file, const $group_dset_dtype$* $group_dset$,
const uint32_t rank, const uint64_t* dims)
trexio_hdf5_write_$group_dset$ (trexio_t* const file, const $group_dset_dtype$* $group_dset$, const uint32_t rank, const uint64_t* dims)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
@ -386,7 +388,7 @@ trexio_hdf5_write_$group_dset$ (trexio_t* const file, const $group_dset_dtype$*
}
#+end_src
#+begin_src c :tangle has_dset_hdf5.c
#+begin_src c :tangle has_dset_data_hdf5.c
trexio_exit_code
trexio_hdf5_has_$group_dset$ (trexio_t* const file)
{
@ -408,6 +410,336 @@ trexio_hdf5_has_$group_dset$ (trexio_t* const file)
}
#+end_src
** Template for HDF5 has/read/write a dataset of strings
#+begin_src c :tangle hrw_dset_str_hdf5.h :exports none
trexio_exit_code trexio_hdf5_has_$group_dset$(trexio_t* const file);
trexio_exit_code trexio_hdf5_read_$group_dset$(trexio_t* const file, char* const $group_dset$, const uint32_t rank, const uint64_t* dims, const uint32_t max_str_len);
trexio_exit_code trexio_hdf5_write_$group_dset$(trexio_t* const file, const char** $group_dset$, const uint32_t rank, const uint64_t* dims);
#+end_src
#+begin_src c :tangle read_dset_str_hdf5.c
trexio_exit_code
trexio_hdf5_read_$group_dset$ (trexio_t* const file, char* const $group_dset$, const uint32_t rank, const uint64_t* dims, const uint32_t max_str_len)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
if ($group_dset$ == NULL) return TREXIO_INVALID_ARG_2;
const trexio_hdf5_t* f = (const trexio_hdf5_t*) file;
herr_t status;
// open the dataset to get its dimensions
hid_t dset_id = H5Dopen(f->$group$_group, $GROUP_DSET$_NAME, H5P_DEFAULT);
if (dset_id <= 0) return TREXIO_INVALID_ID;
// allocate space for the dimensions to be read
hsize_t* ddims = CALLOC( (int) rank, hsize_t);
if (ddims == NULL) {
H5Dclose(dset_id);
return TREXIO_ALLOCATION_FAILED;
}
hid_t dspace = H5Dget_space(dset_id);
if (dset_id <= 0) {
FREE(ddims);
H5Dclose(dset_id);
return TREXIO_INVALID_ID;
}
// get the rank of the dataset in a file
int rrank = H5Sget_simple_extent_dims(dspace, ddims, NULL);
if (rrank != (int) rank) {
FREE(ddims);
H5Dclose(dset_id);
H5Sclose(dspace);
return TREXIO_INVALID_ARG_3;
}
for (int i=0; i<rrank; i++) {
if (ddims[i] != dims[i]) {
H5Dclose(dset_id);
H5Sclose(dspace);
FREE(ddims);
return TREXIO_INVALID_ARG_4;
}
}
FREE(ddims);
hid_t memtype = H5Tcopy (H5T_C_S1);
status = H5Tset_size(memtype, H5T_VARIABLE);
if (status < 0 || memtype <= 0) {
H5Dclose(dset_id);
H5Sclose(dspace);
return TREXIO_FAILURE;
}
char** rdata = CALLOC(dims[0], char*);
if (rdata == NULL) {
H5Dclose(dset_id);
H5Sclose(dspace);
H5Tclose(memtype);
return TREXIO_ALLOCATION_FAILED;
}
status = H5Dread(dset_id, memtype, H5S_ALL, H5S_ALL, H5P_DEFAULT, rdata);
if (status < 0) {
FREE(rdata);
H5Dclose(dset_id);
H5Sclose(dspace);
H5Tclose(memtype);
return TREXIO_FAILURE;
}
// copy contents of temporary rdata buffer into the group_dset otherwise they are lost
// after calling H5Treclaim or H5Dvlen_reclaim functions
strcpy($group_dset$, "");
for (uint64_t i=0; i<dims[0]; i++) {
strncat($group_dset$, rdata[i], max_str_len);
strcat($group_dset$, TREXIO_DELIM);
}
// H5Dvlen_reclaim is deprecated and replaced by H5Treclaim in HDF5 v.1.12.0
#if (H5_VERS_MAJOR <= 1 && H5_VERS_MINOR < 12)
status = H5Dvlen_reclaim(memtype, dspace, H5P_DEFAULT, rdata);
#else
status = H5Treclaim(memtype, dspace, H5P_DEFAULT, rdata);
#endif
if (status < 0) {
FREE(rdata);
H5Dclose(dset_id);
H5Sclose(dspace);
H5Tclose(memtype);
return TREXIO_FAILURE;
}
FREE(rdata);
H5Dclose(dset_id);
H5Sclose(dspace);
H5Tclose(memtype);
return TREXIO_SUCCESS;
}
#+end_src
#+begin_src c :tangle write_dset_str_hdf5.c
trexio_exit_code
trexio_hdf5_write_$group_dset$ (trexio_t* const file, const char** $group_dset$, const uint32_t rank, const uint64_t* dims)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
if ($group_dset$ == NULL) return TREXIO_INVALID_ARG_2;
trexio_exit_code rc;
uint64_t $group_dset_dim$;
// error handling for rc is added by the generator
rc = trexio_hdf5_read_$group_dset_dim$(file, &($group_dset_dim$));
if ($group_dset_dim$ == 0L) return TREXIO_INVALID_NUM;
trexio_hdf5_t* f = (trexio_hdf5_t*) file;
herr_t status;
hid_t dset_id;
/* we are going to write variable-length strings */
hid_t memtype = H5Tcopy (H5T_C_S1);
status = H5Tset_size (memtype, H5T_VARIABLE);
if ( H5LTfind_dataset(f->$group$_group, $GROUP_DSET$_NAME) != 1 ) {
/* code to create dataset */
hid_t filetype = H5Tcopy (H5T_FORTRAN_S1);
status = H5Tset_size (filetype, H5T_VARIABLE);
hid_t dspace = H5Screate_simple( (int) rank, (const hsize_t*) dims, NULL);
dset_id = H5Dcreate (f->$group$_group, $GROUP_DSET$_NAME, filetype, dspace,
H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
if (dset_id <= 0) return TREXIO_INVALID_ID;
status = H5Dwrite (dset_id, memtype,
H5S_ALL, H5S_ALL, H5P_DEFAULT,
$group_dset$);
H5Dclose (dset_id);
H5Sclose (dspace);
H5Tclose (filetype);
H5Tclose (memtype);
if (status < 0) return TREXIO_FAILURE;
} else {
dset_id = H5Dopen(f->$group$_group, $GROUP_DSET$_NAME, H5P_DEFAULT);
if (dset_id <= 0) return TREXIO_INVALID_ID;
/* code to write dataset */
status = H5Dwrite(dset_id, memtype,
H5S_ALL, H5S_ALL, H5P_DEFAULT,
$group_dset$);
H5Dclose(dset_id);
H5Tclose(memtype);
if (status < 0) return TREXIO_FAILURE;
}
return TREXIO_SUCCESS;
}
#+end_src
#+begin_src c :tangle has_dset_str_hdf5.c
trexio_exit_code
trexio_hdf5_has_$group_dset$ (trexio_t* const file)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
trexio_hdf5_t* f = (trexio_hdf5_t*) file;
herr_t status = H5LTfind_dataset(f->$group$_group, $GROUP_DSET$_NAME);
/* H5LTfind_dataset returns 1 if dataset exists, 0 otherwise */
if (status == 1){
return TREXIO_SUCCESS;
} else if (status == 0) {
return TREXIO_HAS_NOT;
} else {
return TREXIO_FAILURE;
}
}
#+end_src
** Template for HDF5 has/read/write a single string attribute
#+begin_src c :tangle hrw_attr_str_hdf5.h :exports none
trexio_exit_code trexio_hdf5_has_$group_str$ (trexio_t* const file);
trexio_exit_code trexio_hdf5_read_$group_str$ (trexio_t* const file, char* const str, const uint32_t max_str_len);
trexio_exit_code trexio_hdf5_write_$group_str$(trexio_t* const file, const char* str);
#+end_src
#+begin_src c :tangle read_attr_str_hdf5.c
trexio_exit_code
trexio_hdf5_read_$group_str$ (trexio_t* const file, char* const str, const uint32_t max_str_len)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
if (str == NULL) return TREXIO_INVALID_ARG_2;
const trexio_hdf5_t* f = (const trexio_hdf5_t*) file;
/* Quit if the string attribute is missing in the file */
if (H5Aexists(f->$group$_group, $GROUP_STR$_NAME) == 0) return TREXIO_HAS_NOT;
/* Read the $group_str$ attribute of $group$ group */
const hid_t str_id = H5Aopen(f->$group$_group, $GROUP_STR$_NAME, H5P_DEFAULT);
if (str_id <= 0) return TREXIO_INVALID_ID;
const hid_t ftype_id = H5Aget_type(str_id);
if (ftype_id <= 0) return TREXIO_INVALID_ID;
uint64_t sdim = H5Tget_size(ftype_id);
if (sdim <= 0) return TREXIO_FAILURE;
sdim++; /* Make room for null terminator */
const hid_t mem_id = H5Tcopy(H5T_C_S1);
if (mem_id <= 0) return TREXIO_INVALID_ID;
herr_t status;
status = (max_str_len+1) > sdim ? H5Tset_size(mem_id, sdim) : H5Tset_size(mem_id, max_str_len+1) ;
if (status < 0) return TREXIO_FAILURE;
status = H5Aread(str_id, mem_id, str);
if (status < 0) return TREXIO_FAILURE;
H5Aclose(str_id);
H5Tclose(mem_id);
H5Tclose(ftype_id);
return TREXIO_SUCCESS;
}
#+end_src
#+begin_src c :tangle write_attr_str_hdf5.c
trexio_exit_code
trexio_hdf5_write_$group_str$ (trexio_t* const file, const char* str)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
if (str == NULL) return TREXIO_INVALID_ARG_2;
trexio_hdf5_t* const f = (trexio_hdf5_t*) file;
/* Setup the dataspace */
const hid_t dtype_id = H5Tcopy(H5T_C_S1);
if (dtype_id <= 0) return TREXIO_INVALID_ID;
size_t str_attr_len = strlen(str) + 1;
herr_t status;
status = H5Tset_size(dtype_id, str_attr_len);
if (status < 0) return TREXIO_FAILURE;
status = H5Tset_strpad(dtype_id, H5T_STR_NULLTERM);
if (status < 0) return TREXIO_FAILURE;
const hid_t dspace_id = H5Screate(H5S_SCALAR);
if (dspace_id <= 0) return TREXIO_INVALID_ID;
/* Create the $group_str$ attribute of $group$ group */
const hid_t str_id = H5Acreate(f->$group$_group, $GROUP_STR$_NAME, dtype_id, dspace_id,
H5P_DEFAULT, H5P_DEFAULT);
if (str_id <= 0) {
H5Sclose(dspace_id);
H5Tclose(dtype_id);
return TREXIO_INVALID_ID;
}
status = H5Awrite(str_id, dtype_id, str);
if (status < 0) {
H5Aclose(str_id);
H5Sclose(dspace_id);
H5Tclose(dtype_id);
return TREXIO_FAILURE;
}
H5Aclose(str_id);
H5Sclose(dspace_id);
H5Tclose(dtype_id);
return TREXIO_SUCCESS;
}
#+end_src
#+begin_src c :tangle has_attr_str_hdf5.c
trexio_exit_code
trexio_hdf5_has_$group_str$ (trexio_t* const file)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
const trexio_hdf5_t* f = (const trexio_hdf5_t*) file;
htri_t status = H5Aexists(f->$group$_group, $GROUP_STR$_NAME);
/* H5Aexists returns positive value if attribute exists, 0 if does not, negative if error */
if (status > 0){
return TREXIO_SUCCESS;
} else if (status == 0) {
return TREXIO_HAS_NOT;
} else {
return TREXIO_FAILURE;
}
}
#+end_src
* Constant file suffixes (not used by the generator) :noexport:
#+begin_src c :tangle suffix_hdf5.h

View File

@ -17,14 +17,22 @@ cat populated/pop_free_group_text.h >> trexio_text.h
cat populated/pop_read_group_text.h >> trexio_text.h
cat populated/pop_flush_group_text.h >> trexio_text.h
cat populated/pop_has_dset_text.c >> trexio_text.c
cat populated/pop_has_dset_data_text.c >> trexio_text.c
cat populated/pop_has_dset_str_text.c >> trexio_text.c
cat populated/pop_has_num_text.c >> trexio_text.c
cat populated/pop_read_dset_text.c >> trexio_text.c
cat populated/pop_has_attr_str_text.c >> trexio_text.c
cat populated/pop_read_dset_data_text.c >> trexio_text.c
cat populated/pop_read_dset_str_text.c >> trexio_text.c
cat populated/pop_read_attr_str_text.c >> trexio_text.c
cat populated/pop_read_num_text.c >> trexio_text.c
cat populated/pop_write_dset_text.c >> trexio_text.c
cat populated/pop_write_dset_data_text.c >> trexio_text.c
cat populated/pop_write_dset_str_text.c >> trexio_text.c
cat populated/pop_write_attr_str_text.c >> trexio_text.c
cat populated/pop_write_num_text.c >> trexio_text.c
cat populated/pop_hrw_num_text.h >> trexio_text.h
cat populated/pop_hrw_dset_text.h >> trexio_text.h
cat populated/pop_hrw_dset_data_text.h >> trexio_text.h
cat populated/pop_hrw_dset_str_text.h >> trexio_text.h
cat populated/pop_hrw_attr_str_text.h >> trexio_text.h
cat rdm_text.c >> trexio_text.c
cat rdm_text.h >> trexio_text.h

View File

@ -83,6 +83,8 @@ typedef struct $group$_s {
uint32_t rank_$group_dset$;
uint32_t to_flush;
uint64_t dims_$group_dset$[16];
uint64_t len_$group_str$;
char* $group_str$;
char file_name[TREXIO_MAX_FILENAME_LENGTH];
} $group$_t;
#+end_src
@ -298,7 +300,7 @@ trexio_text_read_$group$ (trexio_text_t* const file)
/* Read the dimensioning variables */
int rc;
// START REPEAT GROUP_DSET
// START REPEAT GROUP_DSET_ALL
rc = fscanf(f, "%1023s", buffer);
if ((rc != 1) || (strcmp(buffer, "rank_$group_dset$") != 0)) {
FREE(buffer);
@ -319,9 +321,9 @@ trexio_text_read_$group$ (trexio_text_t* const file)
uint64_t size_$group_dset$ = 0;
if ($group$->rank_$group_dset$ != 0) size_$group_dset$ = 1;
for (unsigned int i=0; i<$group$->rank_$group_dset$; ++i){
for (uint32_t i=0; i<$group$->rank_$group_dset$; ++i){
unsigned int j=0;
uint32_t j=0;
rc = fscanf(f, "%1023s %u", buffer, &j);
if ((rc != 2) || (strcmp(buffer, "dims_$group_dset$") != 0) || (j!=i)) {
@ -342,7 +344,7 @@ trexio_text_read_$group$ (trexio_text_t* const file)
size_$group_dset$ *= $group$->dims_$group_dset$[i];
}
// END REPEAT GROUP_DSET
// END REPEAT GROUP_DSET_ALL
// START REPEAT GROUP_NUM
/* Read data */
@ -365,13 +367,68 @@ trexio_text_read_$group$ (trexio_text_t* const file)
}
// END REPEAT GROUP_NUM
// START REPEAT GROUP_DSET
// START REPEAT GROUP_ATTR_STR
rc = fscanf(f, "%1023s", buffer);
assert(!((rc != 1) || (strcmp(buffer, "len_$group_str$") != 0)));
if ((rc != 1) || (strcmp(buffer, "len_$group_str$") != 0)) {
FREE(buffer);
fclose(f);
FREE($group$);
return NULL;
}
rc = fscanf(f, "%" SCNu64 "", &($group$->len_$group_str$));
assert(!(rc != 1));
if (rc != 1) {
FREE(buffer);
fclose(f);
FREE($group$);
return NULL;
}
rc = fscanf(f, "%1023s", buffer);
assert(!((rc != 1) || (strcmp(buffer, "$group_str$") != 0)));
if ((rc != 1) || (strcmp(buffer, "$group_str$") != 0)) {
FREE(buffer);
fclose(f);
FREE($group$->$group_str$);
FREE($group$);
return NULL;
}
if ($group$->len_$group_str$ != 0) {
$group$->$group_str$ = CALLOC($group$->len_$group_str$, char);
assert (!($group$->$group_str$ == NULL));
if ($group$->$group_str$ == NULL) {
FREE(buffer);
fclose(f);
FREE($group$->$group_str$);
FREE($group$);
return NULL;
}
rc = fscanf(f, " %1023[^\n]", $group$->$group_str$);
assert(!(rc != 1));
if (rc != 1) {
FREE(buffer);
fclose(f);
FREE($group$->$group_str$);
FREE($group$);
return NULL;
}
}
// END REPEAT GROUP_ATTR_STR
// START REPEAT GROUP_DSET_NUM
/* Allocate arrays */
$group$->$group_dset$ = CALLOC(size_$group_dset$, $group_dset_dtype$);
assert (!($group$->$group_dset$ == NULL));
if ($group$->$group_dset$ == NULL) {
FREE(buffer);
fclose(f);
FREE($group$->$group_dset$);
FREE($group$);
return NULL;
}
@ -397,7 +454,57 @@ trexio_text_read_$group$ (trexio_text_t* const file)
return NULL;
}
}
// END REPEAT GROUP_DSET
// END REPEAT GROUP_DSET_NUM
size_t tmp_len;
// START REPEAT GROUP_DSET_STR
/* Allocate arrays */
$group$->$group_dset$ = CALLOC(size_$group_dset$, $group_dset_dtype$);
assert (!($group$->$group_dset$ == NULL));
if ($group$->$group_dset$ == NULL) {
FREE(buffer);
fclose(f);
FREE($group$->$group_dset$);
FREE($group$);
return NULL;
}
rc = fscanf(f, "%1023s", buffer);
assert(!((rc != 1) || (strcmp(buffer, "$group_dset$") != 0)));
if ((rc != 1) || (strcmp(buffer, "$group_dset$") != 0)) {
FREE(buffer);
fclose(f);
FREE($group$->$group_dset$);
FREE($group$);
return NULL;
}
/* WARNING: this tmp array allows to avoid allocation of space for each element of array of string
, BUT it's size has to be number_of_str*max_len_str where max_len_str is somewhat arbitrary, e.g. 32.
,*/
char* tmp_$group_dset$;
if(size_$group_dset$ != 0) tmp_$group_dset$ = CALLOC(size_$group_dset$*32, char);
tmp_len = 0;
for (uint64_t i=0 ; i<size_$group_dset$ ; ++i) {
$group$->$group_dset$[i] = tmp_$group_dset$;
/* conventional fcanf with "%s" only return the string before the first space character
,* to read string with spaces use "%[^\n]" possible with space before or after, i.e. " %[^\n]"
,* Q: depending on what ? */
rc = fscanf(f, " %1023[^\n]", tmp_$group_dset$);
assert(!(rc != 1));
if (rc != 1) {
FREE(buffer);
fclose(f);
FREE($group$->$group_dset$);
FREE($group$);
return NULL;
}
tmp_len = strlen($group$->$group_dset$[i]);
tmp_$group_dset$ += tmp_len + 1;
}
// END REPEAT GROUP_DSET_STR
FREE(buffer);
fclose(f);
@ -437,7 +544,7 @@ trexio_text_flush_$group$ (trexio_text_t* const file)
if (f == NULL) return TREXIO_INVALID_ARG_1;
/* Write the dimensioning variables */
// START REPEAT GROUP_DSET
// START REPEAT GROUP_DSET_ALL
fprintf(f, "rank_$group_dset$ %u\n", $group$->rank_$group_dset$);
// workaround for the case of missing blocks in the file
uint64_t size_$group_dset$ = 0;
@ -447,21 +554,26 @@ trexio_text_flush_$group$ (trexio_text_t* const file)
fprintf(f, "dims_$group_dset$ %u %" PRIu64 "\n", i, $group$->dims_$group_dset$[i]);
size_$group_dset$ *= $group$->dims_$group_dset$[i];
}
// END REPEAT GROUP_DSET
// END REPEAT GROUP_DSET_ALL
// START REPEAT GROUP_NUM
fprintf(f, "$group_num$ %" PRIu64 "\n", $group$->$group_num$);
// END REPEAT GROUP_NUM
// START REPEAT GROUP_ATTR_STR
fprintf(f, "len_$group_str$ %" PRIu64 "\n", $group$->len_$group_str$);
fprintf(f, "$group_str$\n");
if ($group$->len_$group_str$ != 0) fprintf(f, "%s\n", $group$->$group_str$);
// END REPEAT GROUP_ATTR_STR
/* Write arrays */
// START REPEAT GROUP_DSET
// START REPEAT GROUP_DSET_ALL
fprintf(f, "$group_dset$\n");
for (uint64_t i=0 ; i<size_$group_dset$ ; ++i) {
fprintf(f, "%$group_dset_std_dtype_out$\n", $group$->$group_dset$[i]);
}
// END REPEAT GROUP_DSET
// END REPEAT GROUP_DSET_ALL
fclose(f);
$group$->to_flush = 0;
@ -493,11 +605,20 @@ trexio_text_free_$group$ (trexio_text_t* const file)
$group$_t* $group$ = file->$group$;
if ($group$ == NULL) return TREXIO_SUCCESS;
// START REPEAT GROUP_DSET
// START REPEAT GROUP_DSET_NUM
if ($group$->$group_dset$ != NULL) FREE ($group$->$group_dset$);
// END REPEAT GROUP_DSET_NUM
// START REPEAT GROUP_DSET_STR
if ($group$->$group_dset$ != NULL) {
if($group$->rank_$group_dset$ != 0) FREE ($group$->$group_dset$[0]);
FREE ($group$->$group_dset$);
}
// END REPEAT GROUP_DSET
// END REPEAT GROUP_DSET_STR
// START REPEAT GROUP_ATTR_STR
if ($group$->$group_str$ != NULL) FREE ($group$->$group_str$);
// END REPEAT GROUP_ATTR_STR
FREE ($group$);
return TREXIO_SUCCESS;
@ -505,7 +626,7 @@ trexio_text_free_$group$ (trexio_text_t* const file)
}
#+end_src
** Template for has/read/write the ~$group_num$~ attribute
** Template for has/read/write the num attribute
#+begin_src c :tangle hrw_num_text.h :exports none
trexio_exit_code trexio_text_has_$group_num$ (trexio_t* const file);
@ -568,17 +689,17 @@ trexio_text_has_$group_num$ (trexio_t* const file)
}
#+end_src
** Template for has/read/write the ~$group_dset$~ dataset
** Template for has/read/write the dataset of numerical data
The ~group_dset~ array is assumed allocated with the appropriate size.
#+begin_src c :tangle hrw_dset_text.h :exports none
#+begin_src c :tangle hrw_dset_data_text.h :exports none
trexio_exit_code trexio_text_has_$group_dset$ (trexio_t* const file);
trexio_exit_code trexio_text_read_$group_dset$ (trexio_t* const file, $group_dset_dtype$* const $group_dset$, const uint32_t rank, const uint64_t* dims);
trexio_exit_code trexio_text_write_$group_dset$(trexio_t* const file, const $group_dset_dtype$* $group_dset$, const uint32_t rank, const uint64_t* dims);
#+end_src
#+begin_src c :tangle read_dset_text.c
#+begin_src c :tangle read_dset_data_text.c
trexio_exit_code
trexio_text_read_$group_dset$ (trexio_t* const file, $group_dset_dtype$* const $group_dset$,
const uint32_t rank, const uint64_t* dims)
@ -593,7 +714,7 @@ trexio_text_read_$group_dset$ (trexio_t* const file, $group_dset_dtype$* const $
if (rank != $group$->rank_$group_dset$) return TREXIO_INVALID_ARG_3;
uint64_t dim_size = 1;
for (unsigned int i=0; i<rank; ++i){
for (uint32_t i=0; i<rank; ++i){
if (dims[i] != $group$->dims_$group_dset$[i]) return TREXIO_INVALID_ARG_4;
dim_size *= dims[i];
}
@ -607,7 +728,7 @@ trexio_text_read_$group_dset$ (trexio_t* const file, $group_dset_dtype$* const $
}
#+end_src
#+begin_src c :tangle write_dset_text.c
#+begin_src c :tangle write_dset_data_text.c
trexio_exit_code
trexio_text_write_$group_dset$ (trexio_t* const file, const $group_dset_dtype$* $group_dset$,
const uint32_t rank, const uint64_t* dims)
@ -628,7 +749,7 @@ trexio_text_write_$group_dset$ (trexio_t* const file, const $group_dset_dtype$*
$group$->rank_$group_dset$ = rank;
uint64_t dim_size = 1;
for (unsigned int i=0; i<$group$->rank_$group_dset$; ++i){
for (uint32_t i=0; i<$group$->rank_$group_dset$; ++i){
$group$->dims_$group_dset$[i] = dims[i];
dim_size *= dims[i];
}
@ -645,7 +766,7 @@ trexio_text_write_$group_dset$ (trexio_t* const file, const $group_dset_dtype$*
}
#+end_src
#+begin_src c :tangle has_dset_text.c
#+begin_src c :tangle has_dset_data_text.c
trexio_exit_code
trexio_text_has_$group_dset$ (trexio_t* const file)
{
@ -663,7 +784,182 @@ trexio_text_has_$group_dset$ (trexio_t* const file)
}
#+end_src
** Template for has/read/write the dataset of strings
The ~group_dset~ array is assumed allocated with the appropriate size.
#+begin_src c :tangle hrw_dset_str_text.h :exports none
trexio_exit_code trexio_text_has_$group_dset$ (trexio_t* const file);
trexio_exit_code trexio_text_read_$group_dset$ (trexio_t* const file, char* const dset, const uint32_t rank, const uint64_t* dims, const uint32_t max_str_len);
trexio_exit_code trexio_text_write_$group_dset$ (trexio_t* const file, const char** dset, const uint32_t rank, const uint64_t* dims);
#+end_src
#+begin_src c :tangle read_dset_str_text.c
trexio_exit_code
trexio_text_read_$group_dset$ (trexio_t* const file, char* const dset, const uint32_t rank, const uint64_t* dims, const uint32_t max_str_len)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
if (dset == NULL) return TREXIO_INVALID_ARG_2;
$group$_t* const $group$ = trexio_text_read_$group$((trexio_text_t*) file);
if ($group$ == NULL) return TREXIO_FAILURE;
if (rank != $group$->rank_$group_dset$) return TREXIO_INVALID_ARG_3;
for (uint32_t i=0 ; i<rank ; ++i) {
if (dims[i] != $group$->dims_$group_dset$[i]) return TREXIO_INVALID_ARG_4;
}
strcpy(dset, "");
for (uint64_t i=0 ; i<dims[0] ; ++i) {
strncat(dset, $group$->$group_dset$[i], max_str_len);
strcat(dset, TREXIO_DELIM);
}
return TREXIO_SUCCESS;
}
#+end_src
#+begin_src c :tangle write_dset_str_text.c
trexio_exit_code
trexio_text_write_$group_dset$ (trexio_t* const file, const char** dset, const uint32_t rank, const uint64_t* dims)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
if (dset == NULL) return TREXIO_INVALID_ARG_2;
if (file->mode == 'r') return TREXIO_READONLY;
$group$_t* const $group$ = trexio_text_read_$group$((trexio_text_t*) file);
if ($group$ == NULL) return TREXIO_FAILURE;
if ($group$->$group_dset$ != NULL) {
if ($group$->rank_$group_dset$ != 0) FREE($group$->$group_dset$[0]);
FREE($group$->$group_dset$);
}
$group$->rank_$group_dset$ = rank;
for (uint32_t i=0; i<$group$->rank_$group_dset$; ++i){
$group$->dims_$group_dset$[i] = dims[i];
}
$group$->$group_dset$ = CALLOC(dims[0], char*);
if ($group$->$group_dset$ == NULL) return TREXIO_ALLOCATION_FAILED;
char* tmp_str = CALLOC(dims[0]*32 + 1, char);
if (tmp_str == NULL) return TREXIO_ALLOCATION_FAILED;
size_t tmp_len = 0;
for (uint64_t i=0 ; i<dims[0] ; ++i) {
tmp_len = strlen(dset[i]);
$group$->$group_dset$[i] = tmp_str;
strncpy(tmp_str, dset[i], tmp_len);
tmp_str += tmp_len + 1;
}
$group$->to_flush = 1;
return TREXIO_SUCCESS;
}
#+end_src
#+begin_src c :tangle has_dset_str_text.c
trexio_exit_code
trexio_text_has_$group_dset$ (trexio_t* const file)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
$group$_t* const $group$ = trexio_text_read_$group$((trexio_text_t*) file);
if ($group$ == NULL) return TREXIO_FAILURE;
if ($group$->rank_$group_dset$ > 0){
return TREXIO_SUCCESS;
} else {
return TREXIO_HAS_NOT;
}
}
#+end_src
** Template for has/read/write the string attribute
#+begin_src c :tangle hrw_attr_str_text.h :exports none
trexio_exit_code trexio_text_has_$group_str$ (trexio_t* const file);
trexio_exit_code trexio_text_read_$group_str$ (trexio_t* const file, char* const str, const uint32_t max_str_len);
trexio_exit_code trexio_text_write_$group_str$ (trexio_t* const file, const char* str);
#+end_src
#+begin_src c :tangle read_attr_str_text.c
trexio_exit_code
trexio_text_read_$group_str$ (trexio_t* const file, char* const str, const uint32_t max_str_len)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
if (str == NULL) return TREXIO_INVALID_ARG_2;
$group$_t* const $group$ = trexio_text_read_$group$((trexio_text_t*) file);
if ($group$ == NULL) return TREXIO_FAILURE;
strncpy(str, $group$->$group_str$, max_str_len);
return TREXIO_SUCCESS;
}
#+end_src
#+begin_src c :tangle write_attr_str_text.c
trexio_exit_code
trexio_text_write_$group_str$ (trexio_t* const file, const char *str)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
if (str == NULL) return TREXIO_INVALID_ARG_2;
if (file->mode == 'r') return TREXIO_READONLY;
$group$_t* const $group$ = trexio_text_read_$group$((trexio_text_t*) file);
if ($group$ == NULL) return TREXIO_FAILURE;
if ($group$->$group_str$ != NULL) FREE($group$->$group_str$);
size_t tmp_len = strlen(str);
$group$->$group_str$ = CALLOC(tmp_len + 1, char);
if ($group$->$group_str$ == NULL) return TREXIO_ALLOCATION_FAILED;
$group$->len_$group_str$ = tmp_len + 1;
strncpy($group$->$group_str$, str, tmp_len + 1);
$group$->to_flush = 1;
return TREXIO_SUCCESS;
}
#+end_src
#+begin_src c :tangle has_attr_str_text.c
trexio_exit_code
trexio_text_has_$group_str$ (trexio_t* const file)
{
if (file == NULL) return TREXIO_INVALID_ARG_1;
$group$_t* const $group$ = trexio_text_read_$group$((trexio_text_t*) file);
if ($group$ == NULL) return TREXIO_FAILURE;
if ($group$->len_$group_str$ > 0){
return TREXIO_SUCCESS;
} else {
return TREXIO_HAS_NOT;
}
}
#+end_src
** RDM struct (hard-coded)
*** Read the complete struct

3
tests/.gitignore vendored
View File

@ -6,6 +6,9 @@ trexio.mod
test_c
test_f
*.log
*.trs
*.h5
*/

View File

@ -2,6 +2,7 @@
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int test_write(const char* file_name, const back_end_t backend);
int test_read(const char* file_name, const back_end_t backend);
@ -54,6 +55,20 @@ int test_write(const char* file_name, const back_end_t backend) {
0.00000000 , 2.47304151 , 0.00000000 ,
};
const char* label[] = {"C" ,
"Na",
"ClH asdasdasdas" ,
"C" ,
"C 666" ,
"C" ,
"H" ,
"Ru",
"H" ,
"H 999asdasd" ,
"H" ,
"H" };
const char* sym = "B3U and some stuff";
/*================= START OF TEST ==================*/
// open file in 'write' mode
@ -72,11 +87,28 @@ int test_write(const char* file_name, const back_end_t backend) {
rc = trexio_write_nucleus_coord(file,coord);
assert (rc == TREXIO_SUCCESS);
rc = trexio_write_nucleus_label(file, label, 32);
assert (rc == TREXIO_SUCCESS);
rc = trexio_write_nucleus_point_group(file, sym, 32);
assert (rc == TREXIO_SUCCESS);
// close current session
rc = trexio_close(file);
assert (rc == TREXIO_SUCCESS);
// reopen file in 'write' mode
file = trexio_open(file_name, 'w', backend);
assert (file != NULL);
// check if the written data exists in the file
rc = trexio_has_nucleus_num(file);
assert (rc == TREXIO_SUCCESS);
rc = trexio_has_nucleus_coord(file);
assert (rc == TREXIO_SUCCESS);
rc = trexio_has_nucleus_label(file);
assert (rc == TREXIO_SUCCESS);
rc = trexio_has_nucleus_point_group(file);
assert (rc == TREXIO_SUCCESS);
// should not work: try to overwrite the num variable
rc = trexio_write_nucleus_num(file,25);
@ -118,6 +150,8 @@ int test_read(const char* file_name, const back_end_t backend) {
int num;
double* coord;
char** label;
char* point_group;
/*================= START OF TEST ==================*/
@ -137,6 +171,37 @@ int test_read(const char* file_name, const back_end_t backend) {
double x = coord[30] - 2.14171677;
assert( x*x < 1.e-14);
free(coord);
// read nucleus_label
label = (char**) malloc(num*sizeof(char*));
for (int i=0; i<num; i++){
label[i] = (char*) malloc(32*sizeof(char));
}
rc = trexio_read_nucleus_label(file, label, 2);
assert (rc == TREXIO_SUCCESS);
assert (strcmp(label[0], "C") == 0);
assert (strcmp(label[1], "Na") == 0);
for (int i=0; i<num; i++){
free(label[i]);
}
free(label);
point_group = (char*) malloc(32*sizeof(char));
rc = trexio_read_nucleus_point_group(file, point_group, 6);
assert (rc == TREXIO_SUCCESS);
char * pch;
pch = strtok(point_group, " ");
assert (strcmp(pch, "B3U") == 0);
/* alternative test when 3 symbols are read from the file to point_group */
/*rc = trexio_read_nucleus_point_group(file, point_group, 3);
assert (rc == TREXIO_SUCCESS);
assert (strcmp(point_group, "B3U") == 0 );*/
free(point_group);
// close current session
rc = trexio_close(file);
@ -150,8 +215,7 @@ int test_read(const char* file_name, const back_end_t backend) {
assert (file2 == NULL);
/*================= END OF TEST =====================*/
free(coord);
return 0;
}

View File

@ -2,19 +2,19 @@ program test_trexio
use trexio
implicit none
call system('rm -rf trexio_test_fort')
print *, 'call test_write(''trexio_test_fort'', TREXIO_TEXT)'
call test_write('trexio_test_fort', TREXIO_TEXT)
print *, 'call test_read(''trexio_test_fort'', TREXIO_TEXT)'
call test_read('trexio_test_fort', TREXIO_TEXT)
call system('rm -rf trexio_test_fort')
call system('rm -rf test_write_f.dir')
print *, 'call test_write(''test_write_f.dir'', TREXIO_TEXT)'
call test_write('test_write_f.dir', TREXIO_TEXT)
print *, 'call test_read(''test_write_f.dir'', TREXIO_TEXT)'
call test_read('test_write_f.dir', TREXIO_TEXT)
call system('rm -rf test_write_f.dir')
call system('rm -rf trexio_test_fort')
print *, 'call test_write(''trexio_test_fort.h5'', TREXIO_HDF5)'
call test_write('trexio_test_fort.h5', TREXIO_HDF5)
print *, 'call test_read(''trexio_test_fort.h5'', TREXIO_HDF5)'
call test_read('trexio_test_fort.h5', TREXIO_HDF5)
call system('rm -rf trexio_test_fort.h5')
call system('rm -rf test_write_f.h5')
print *, 'call test_write(''test_write_f.h5'', TREXIO_HDF5)'
call test_write('test_write_f.h5', TREXIO_HDF5)
print *, 'call test_read(''test_write_f.h5'', TREXIO_HDF5)'
call test_read('test_write_f.h5', TREXIO_HDF5)
call system('rm -rf test_write_f.h5')
end program test_trexio
@ -23,22 +23,26 @@ subroutine test_write(file_name, back_end)
! ============ Test write functionality =============== !
use trexio
use, intrinsic :: iso_c_binding
implicit none
character*(*), intent(in) :: file_name
integer(trexio_backend), intent(in) :: back_end
integer, intent(in) :: back_end
integer(8) :: trex_file
integer :: rc = 1
integer :: num
character*(128) :: str
integer :: num
integer :: basis_nucleus_index(12)
double precision :: charge(12)
double precision :: coord(3,12)
character(len=:), allocatable :: sym_str
character(len=:), allocatable :: label(:)
! parameters to be written
num = 12
charge = (/ 6., 6., 6., 6., 6., 6., 1., 1., 1., 1., 1., 1. /)
@ -58,117 +62,56 @@ subroutine test_write(file_name, back_end)
basis_nucleus_index = (/ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 /)
label = [character(len=8) :: 'C', 'Na','C', 'C 66', 'C','C', 'H 99', 'Ru', 'H', 'H', 'H', 'H' ]
sym_str = 'B3U with some comments'
! ================= START OF TEST ===================== !
trex_file = trexio_open(file_name, 'w', back_end)
rc = trexio_has_nucleus_num(trex_file)
if (rc == TREXIO_HAS_NOT) then
write(*,*) 'SUCCESS HAS NOT 1'
else
call trexio_string_of_error(rc,str)
print *, trim(str)
call exit(1)
endif
call trexio_assert(rc, TREXIO_HAS_NOT, 'SUCCESS HAS NOT 1')
rc = trexio_has_nucleus_charge(trex_file)
if (rc == TREXIO_HAS_NOT) then
write(*,*) 'SUCCESS HAS NOT 2'
else
call trexio_string_of_error(rc,str)
print *, trim(str)
call exit(1)
endif
call trexio_assert(rc, TREXIO_HAS_NOT, 'SUCCESS HAS NOT 2')
rc = trexio_write_nucleus_num(trex_file, num)
if (rc == TREXIO_SUCCESS) then
write(*,*) 'SUCCESS WRITE NUM'
else
call trexio_string_of_error(rc,str)
print *, trim(str)
call exit(1)
endif
call trexio_assert(rc, TREXIO_SUCCESS, 'SUCCESS WRITE NUM')
rc = trexio_write_nucleus_charge(trex_file, charge)
if (rc == TREXIO_SUCCESS) then
write(*,*) 'SUCCESS WRITE CHARGE'
else
call trexio_string_of_error(rc,str)
print *, trim(str)
call exit(1)
endif
call trexio_assert(rc, TREXIO_SUCCESS, 'SUCCESS WRITE CHARGE')
rc = trexio_write_nucleus_coord(trex_file, coord)
if (rc == TREXIO_SUCCESS) then
write(*,*) 'SUCCESS WRITE COORD'
else
call trexio_string_of_error(rc,str)
print *, trim(str)
call exit(1)
endif
call trexio_assert(rc, TREXIO_SUCCESS, 'SUCCESS WRITE COORD')
rc = trexio_has_nucleus_num(trex_file)
if (rc == TREXIO_SUCCESS) then
write(*,*) 'SUCCESS HAS 1'
else
call trexio_string_of_error(rc,str)
print *, trim(str)
call exit(1)
endif
rc = trexio_write_nucleus_label(trex_file, label, 5)
call trexio_assert(rc, TREXIO_SUCCESS, 'SUCCESS WRITE LABEL')
deallocate(label)
rc = trexio_write_nucleus_point_group(trex_file, sym_str, 32)
deallocate(sym_str)
call trexio_assert(rc, TREXIO_SUCCESS, 'SUCCESS WRITE POINT GROUP')
rc = trexio_has_nucleus_coord(trex_file)
if (rc == TREXIO_SUCCESS) then
write(*,*) 'SUCCESS HAS 2'
else
call trexio_string_of_error(rc,str)
print *, trim(str)
call exit(1)
endif
rc = trexio_write_basis_nucleus_index(trex_file, basis_nucleus_index)
if (rc == TREXIO_SUCCESS) then
write(*,*) 'SUCCESS WRITE INDEX'
else
call trexio_string_of_error(rc,str)
print *, trim(str)
call exit(1)
endif
call trexio_assert(rc, TREXIO_SUCCESS, 'SUCCESS WRITE INDEX')
rc = trexio_has_nucleus_num(trex_file)
call trexio_assert(rc, TREXIO_SUCCESS, 'SUCCESS HAS 1')
rc = trexio_has_nucleus_coord(trex_file)
call trexio_assert(rc, TREXIO_SUCCESS, 'SUCCESS HAS 2')
rc = trexio_close(trex_file)
if (rc == TREXIO_SUCCESS) then
write(*,*) 'SUCCESS CLOSE'
else
call trexio_string_of_error(rc,str)
print *, trim(str)
call exit(1)
endif
! ---------------------------------- !
! to modify fields of existing file:
! text backend -> open with 'w'
! hdf5 backend -> open with 'a'
! ---------------------------------- !
!! trex_file = trexio_open('trexio_test_fort', 'w', TREXIO_TEXT);
!! trex_file = trexio_open('test_hdf5_fort.h5', 'a', TREXIO_HDF5)
! coord(1) = 666.666
! rc = trexio_write_nucleus_coord(trex_file,coord)
! if (rc == TREXIO_SUCCESS) write(*,*) 'SUCCESS MODIFY COORD'
! rc = trexio_close(trex_file)
! if (rc == TREXIO_SUCCESS) write(*,*) 'SUCCESS CLOSE'
call trexio_assert(rc, TREXIO_SUCCESS, 'SUCCESS CLOSE')
! ================= END OF TEST ===================== !
end subroutine test_write
subroutine test_read(file_name, back_end)
! ============ Test read functionality =============== !
@ -177,10 +120,11 @@ subroutine test_read(file_name, back_end)
implicit none
character*(*), intent(in) :: file_name
integer(trexio_backend), intent(in) :: back_end
integer, intent(in) :: back_end
integer(8) :: trex_file
integer :: i, j, k, ind, offset, flag
integer :: rc = 1
integer :: num, num_read
@ -188,6 +132,12 @@ subroutine test_read(file_name, back_end)
double precision :: charge(12)
double precision :: coord(3,12)
character :: label_str(128)
character(len=4) :: tmp_str
character(len=4) :: label(12) ! also works with allocatable arrays
character(len=32) :: sym_str
character*(128) :: str
num = 12
@ -196,56 +146,69 @@ subroutine test_read(file_name, back_end)
trex_file = trexio_open(file_name, 'r', back_end)
rc = trexio_read_nucleus_num(trex_file, num_read)
if (rc == TREXIO_SUCCESS .and. num_read == num) then
rc = trexio_read_nucleus_num(trex_file, num_read)
call trexio_assert(rc, TREXIO_SUCCESS)
if (num_read == num) then
write(*,*) 'SUCCESS READ NUM'
else
call trexio_string_of_error(rc,str)
print *, trim(str)
call exit(1)
print *, 'FAILURE NUM CHECK'
call exit(-1)
endif
rc = trexio_read_nucleus_charge(trex_file, charge)
if (rc == TREXIO_SUCCESS .and. (dabs(charge(11) - 1.d0) < 1.0D-8) ) then
call trexio_assert(rc, TREXIO_SUCCESS)
if (dabs(charge(11) - 1.d0) < 1.0D-8) then
write(*,*) 'SUCCESS READ CHARGE'
else
call trexio_string_of_error(rc,str)
print *, trim(str)
print *, 'FAILURE CHARGE CHECK'
call exit(-1)
endif
rc = trexio_read_nucleus_coord(trex_file, coord)
if (rc == TREXIO_SUCCESS .and. (dabs(coord(2,1) - 1.39250319d0) < 1.0D-8) ) then
call trexio_assert(rc, TREXIO_SUCCESS)
if (dabs(coord(2,1) - 1.39250319d0) < 1.0D-8) then
write(*,*) 'SUCCESS READ COORD'
else
call trexio_string_of_error(rc,str)
print *, trim(str)
print *, 'FAILURE COORD CHECK'
call exit(-1)
endif
rc = trexio_read_nucleus_label(trex_file, label, 2)
call trexio_assert(rc, TREXIO_SUCCESS)
if (trim(label(2)) == 'Na') then
write(*,*) 'SUCCESS READ LABEL'
else
print *, 'FAILURE LABEL CHECK'
call exit(-1)
endif
rc = trexio_read_basis_nucleus_index(trex_file, basis_nucleus_index)
if (rc == TREXIO_SUCCESS .and. (basis_nucleus_index(12) == 12) ) then
call trexio_assert(rc, TREXIO_SUCCESS)
if (basis_nucleus_index(12) == 12) then
write(*,*) 'SUCCESS READ INDEX'
else
call trexio_string_of_error(rc,str)
print *, trim(str)
print *, 'FAILURE INDEX CHECK'
call exit(-1)
endif
rc = trexio_read_nucleus_point_group(trex_file, sym_str, 10)
call trexio_assert(rc, TREXIO_SUCCESS)
if (sym_str(1:3) == 'B3U') then
write(*,*) 'SUCCESS READ POINT GROUP'
else
print *, 'FAILURE POINT GROUP CHECK'
call exit(-1)
endif
rc = trexio_close(trex_file)
if (rc == TREXIO_SUCCESS) then
write(*,*) 'SUCCESS CLOSE'
else
call trexio_string_of_error(rc,str)
print *, trim(str)
call exit(1)
endif
call trexio_assert(rc, TREXIO_SUCCESS)
! ================= END OF TEST ===================== !

View File

@ -18,12 +18,15 @@ print('Strings I/O currently not supported')
# -------------------- GET ATTRIBUTES FROM THE CONFIGURATION ---------------- #
group_dict = get_group_dict(trex_config)
detailed_num = get_detailed_num_dict(trex_config)
# helper dictionaries contain group, num or dset names as keys
datasets = get_dset_dict(trex_config)
detailed_dset_nostr, detailed_dset_str = split_dset_dict_detailed(datasets)
detailed_nums = get_detailed_num_dict(trex_config)
detailed_strs = get_detailed_str_dict(trex_config)
# helper dictionaries that contain names of groups, nums or dsets as keys
dsets = get_dset_dict(trex_config)
detailed_dsets_nostr, detailed_dsets_str = split_dset_dict_detailed(dsets)
detailed_dsets = detailed_dsets_nostr.copy()
detailed_dsets.update(detailed_dsets_str)
# consistency check for dimensioning variables
check_dim_consistency(detailed_num, datasets)
check_dim_consistency(detailed_nums, dsets)
# --------------------------------------------------------------------------- #
# -------------------- GET TEMPLATED FILES TO BE POPULATED ------------------ #
@ -40,18 +43,26 @@ files_todo = get_files_todo(source_files)
# populate files with iterative scheme, i.e. for unique functions
for fname in files_todo['auxiliary']:
iterative_populate_file(fname, template_paths, group_dict, detailed_dset_nostr, detailed_num)
iterative_populate_file(fname, template_paths, group_dict, detailed_dsets, detailed_nums, detailed_strs)
# populate has/read/write_num functions with recursive scheme
for fname in files_todo['num']:
recursive_populate_file(fname, template_paths, detailed_num)
recursive_populate_file(fname, template_paths, detailed_nums)
# populate has/read/write_dset functions with recursive scheme
for fname in files_todo['dset']:
recursive_populate_file(fname, template_paths, detailed_dset_nostr)
# populate has/read/write_str functions with recursive scheme
for fname in files_todo['attr_str']:
recursive_populate_file(fname, template_paths, detailed_strs)
# populate has/read/write_dset (numerical) functions with recursive scheme
for fname in files_todo['dset_data']:
recursive_populate_file(fname, template_paths, detailed_dsets_nostr)
# populate has/read/write_dset (strings) functions with recursive scheme
for fname in files_todo['dset_str']:
recursive_populate_file(fname, template_paths, detailed_dsets_str)
# populate group-related functions with mixed (iterative+recursive) scheme [text backend]
for fname in files_todo['group']:
special_populate_text_group(fname, template_paths, group_dict, detailed_dset_nostr, detailed_num)
special_populate_text_group(fname, template_paths, group_dict, detailed_dsets, detailed_nums, detailed_strs)
# --------------------------------------------------------------------------- #

View File

@ -39,11 +39,11 @@ def get_files_todo(source_files: dict) -> dict:
files_todo = {}
#files_todo['all'] = list(filter(lambda x: 'read' in x or 'write' in x or 'has' in x or 'hrw' in x or 'flush' in x or 'free' in x, all_files))
files_todo['all'] = [f for f in all_files if 'read' in f or 'write' in f or 'has' in f or 'flush' in f or 'free' in f or 'hrw' in f]
for key in ['dset', 'num', 'group']:
for key in ['dset_data', 'dset_str', 'num', 'attr_str', 'group']:
files_todo[key] = list(filter(lambda x: key in x, files_todo['all']))
files_todo['group'].append('struct_text_group_dset.h')
# files that correspond to todo1 group (e.g. only iterative population within the function body)
# files that correspond to iterative population (e.g. the code is repeated within the function body but the function itself is unique)
files_todo['auxiliary'] = ['def_hdf5.c', 'basic_hdf5.c', 'basic_text_group.c', 'struct_hdf5.h', 'struct_text_group.h']
return files_todo
@ -104,7 +104,7 @@ def recursive_populate_file(fname: str, paths: dict, detailed_source: dict) -> N
'group_dset_f_dtype_default', 'group_dset_f_dtype_double', 'group_dset_f_dtype_single',
'group_dset_dtype_default', 'group_dset_dtype_double', 'group_dset_dtype_single',
'group_dset_rank', 'group_dset_dim_list', 'group_dset_f_dims',
'group_dset', 'group_num', 'group']
'group_dset', 'group_num', 'group_str', 'group']
for item in detailed_source.keys():
with open(join(templ_path,fname), 'r') as f_in :
@ -119,7 +119,7 @@ def recursive_populate_file(fname: str, paths: dict, detailed_source: dict) -> N
if not dim.isdigit() and not dim in num_written:
num_written.append(dim)
templine = line.replace('$group_dset_dim$', dim)
if '_read' in templine:
if '_read' in templine and (not 'fortran' in fname):
line_toadd = indentlevel*" " + rc_line
templine += line_toadd
@ -168,7 +168,7 @@ def recursive_replace_line (input_line: str, triggers: list, source: dict) -> st
return output_line
def iterative_populate_file (filename: str, paths: dict, groups: dict, datasets: dict, numbers: dict) -> None:
def iterative_populate_file (filename: str, paths: dict, groups: dict, datasets: dict, numbers: dict, strings: dict) -> None:
"""
Iteratively populate files with unique functions that contain templated variables.
@ -178,12 +178,13 @@ def iterative_populate_file (filename: str, paths: dict, groups: dict, datasets:
groups (dict) : dictionary of groups
datasets (dict) : dictionary of datasets with substitution details
numbers (dict) : dictionary of numbers with substitution details
strings (dict) : dictionary of strings with substitution details
Returns:
None
"""
add_trigger = 'rc = trexio_text_free_$group$'
triggers = [add_trigger, '$group_dset$', '$group_num$', '$group$']
triggers = [add_trigger, '$group_dset$', '$group_num$', '$group_str$', '$group$']
templ_path = get_template_path(filename, paths)
filename_out = join('populated',f'pop_{filename}')
@ -197,7 +198,7 @@ def iterative_populate_file (filename: str, paths: dict, groups: dict, datasets:
if id == 0:
# special case for proper error handling when deallocting text groups
error_handler = ' if (rc != TREXIO_SUCCESS) return rc;\n'
populated_line = iterative_replace_line(line, triggers[3], groups, add_line=error_handler)
populated_line = iterative_replace_line(line, '$group$', groups, add_line=error_handler)
f_out.write(populated_line)
elif id == 1:
populated_line = iterative_replace_line(line, triggers[id], datasets, None)
@ -206,6 +207,9 @@ def iterative_populate_file (filename: str, paths: dict, groups: dict, datasets:
populated_line = iterative_replace_line(line, triggers[id], numbers, None)
f_out.write(populated_line)
elif id == 3:
populated_line = iterative_replace_line(line, triggers[id], strings, None)
f_out.write(populated_line)
elif id == 4:
populated_line = iterative_replace_line(line, triggers[id], groups, None)
f_out.write(populated_line)
else:
@ -257,7 +261,7 @@ def check_triggers (input_line: str, triggers: list) -> int:
return out_id
def special_populate_text_group(fname: str, paths: dict, group_dict: dict, detailed_dset: dict, detailed_numbers: dict) -> None:
def special_populate_text_group(fname: str, paths: dict, group_dict: dict, detailed_dset: dict, detailed_numbers: dict, detailed_strings: dict) -> None:
"""
Special population for group-related functions in the TEXT back end.
@ -267,6 +271,7 @@ def special_populate_text_group(fname: str, paths: dict, group_dict: dict, detai
group_dict (dict) : dictionary of groups
detailed_dset (dict) : dictionary of datasets with substitution details
detailed_numbers (dict) : dictionary of numbers with substitution details
detailed_strings (dict) : dictionary of string attributes with substitution details
Returns:
None
@ -275,7 +280,7 @@ def special_populate_text_group(fname: str, paths: dict, group_dict: dict, detai
templ_path = get_template_path(fname, paths)
triggers = ['group_dset_dtype', 'group_dset_std_dtype_out', 'group_dset_std_dtype_in',
'group_dset', 'group_num', 'group']
'group_dset', 'group_num', 'group_str', 'group']
for group in group_dict.keys():
@ -286,13 +291,15 @@ def special_populate_text_group(fname: str, paths: dict, group_dict: dict, detai
subloop_num = False
loop_body = ''
dset_allocated = []
str_allocated = []
for line in f_in :
if 'START REPEAT GROUP_DSET' in line:
subloop_dset = True
continue
elif 'START REPEAT GROUP_NUM' in line:
# this can be merged in one later using something like START REPEAT GROUP_ATTR in line
elif 'START REPEAT GROUP_NUM' in line or 'START REPEAT GROUP_ATTR_STR' in line:
subloop_num = True
continue
@ -302,6 +309,11 @@ def special_populate_text_group(fname: str, paths: dict, group_dict: dict, detai
if group != detailed_dset[dset]['group']:
continue
if ('REPEAT GROUP_DSET_STR' in line) and (detailed_dset[dset]['dtype'] != 'char*'):
continue
if ('REPEAT GROUP_DSET_NUM' in line) and (detailed_dset[dset]['dtype'] == 'char*'):
continue
dset_allocated.append(dset)
if 'FREE($group$->$group_dset$)' in loop_body:
@ -309,7 +321,7 @@ def special_populate_text_group(fname: str, paths: dict, group_dict: dict, detai
for dset_alloc in dset_allocated:
tmp_string += f'FREE({group}->{dset_alloc});\n '
tmp_body = loop_body.replace('FREE($group$->$group_dset$);',tmp_string)
tmp_body = loop_body.replace('FREE($group$->$group_dset$);', tmp_string)
populated_body = recursive_replace_line(tmp_body, triggers, detailed_dset[dset])
f_out.write(populated_body)
@ -336,6 +348,33 @@ def special_populate_text_group(fname: str, paths: dict, group_dict: dict, detai
loop_body = ''
continue
elif 'END REPEAT GROUP_ATTR_STR' in line:
for str in detailed_strings.keys():
if group != detailed_strings[str]['group']:
continue
str_allocated.append(str)
if 'FREE($group$->$group_str$)' in loop_body:
tmp_string = ''
for str_alloc in str_allocated:
tmp_string += f'FREE({group}->{str_alloc});\n '
tmp_body = loop_body.replace('FREE($group$->$group_str$);', tmp_string)
populated_body = recursive_replace_line(tmp_body, triggers, detailed_strings[str])
f_out.write(populated_body)
else:
save_body = loop_body
populated_body = recursive_replace_line(save_body, triggers, detailed_strings[str])
f_out.write(populated_body)
subloop_num = False
loop_body = ''
str_allocated = []
continue
if not subloop_num and not subloop_dset:
# NORMAL CASE WITHOUT SUBLOOPS
if '$group_dset' in line:
@ -344,6 +383,12 @@ def special_populate_text_group(fname: str, paths: dict, group_dict: dict, detai
continue
populated_line = recursive_replace_line(line, triggers, detailed_dset[dset])
f_out.write(populated_line)
elif '$group_str' in line:
for str in detailed_strings.keys():
if group != detailed_strings[str]['group']:
continue
populated_line = recursive_replace_line(line, triggers, detailed_strings[str])
f_out.write(populated_line)
elif '$group_num$' in line:
for dim in detailed_numbers.keys():
if group != detailed_numbers[dim]['group']:
@ -420,6 +465,31 @@ def get_detailed_num_dict (configuration: dict) -> dict:
return num_dict
def get_detailed_str_dict (configuration: dict) -> dict:
"""
Returns the dictionary of all `str`-like attributes.
Keys are names, values are subdictionaries containing corresponding group and group_str names.
Parameters:
configuration (dict) : configuration from `trex.json`
Returns:
str_dict (dict) : dictionary of string attributes
"""
str_dict = {}
for k1,v1 in configuration.items():
for k2,v2 in v1.items():
if len(v2[1]) == 0:
tmp_str = f'{k1}_{k2}'
if 'str' in v2[0]:
tmp_dict = {}
tmp_dict['group'] = k1
tmp_dict['group_str'] = tmp_str
str_dict[tmp_str] = tmp_dict
return str_dict
def get_dset_dict (configuration: dict) -> dict:
"""
Returns the dictionary of datasets.
@ -485,8 +555,12 @@ def split_dset_dict_detailed (datasets: dict) -> tuple:
group_dset_std_dtype_out = '" PRId64 "'
group_dset_std_dtype_in = '" SCNd64 "'
elif v[0] == 'str':
# TODO
datatype = 'string'
datatype = 'char*'
group_dset_h5_dtype = 'c_s1'
group_dset_f_dtype_default = 'character(len=*)'
group_dset_dtype_default = 'char*'
group_dset_std_dtype_out = 's'
group_dset_std_dtype_in = 's'
# add the dset name for templates
tmp_dict['group_dset'] = k
@ -532,7 +606,7 @@ def split_dset_dict_detailed (datasets: dict) -> tuple:
tmp_dict['group'] = v[2]
# split datasets in numeric- and string- based
if (datatype == 'string'):
if (datatype == 'char*'):
dset_string_dict[k] = tmp_dict
else:
dset_numeric_dict[k] = tmp_dict