#+Title: TEXT back end of the TREX Input/Ouput library (TREXIO) * File prefixes :noxport: #+NAME:header #+begin_src c /* This file was generated from the trexio.org org-mode file. To generate it, open trexio.org in Emacs and execute M-x org-babel-tangle */ #+end_src #+begin_src c :tangle trexio_text.h :noweb yes <
> #ifndef _TREXIO_TEXT_H #define _TREXIO_TEXT_H #include "trexio.h" #include "trexio_s.h" #include #include #include #include #include #include #include #include #include #+end_src #+begin_src c :tangle trexio_text.c :noweb yes <
> #include "trexio_text.h" #+end_src * TEXT Back end The "file" produced by the text back end is a directory with one file per group. When the file is open, it is locked by the current process. No other process can read/write the same file. This guarantees that the representation in memory is consistent with the file and avoid re-reading the file before writing. To lock the file, we lock the =.lock= file which is present in the directory. The file is written when closed, or when the flush function is called. *** Structs for blocks #+begin_src c :tangle trexio_text.h typedef struct nucleus_s { FILE* file; double* coord; double* charge; uint64_t num; uint64_t* dims_charge; uint64_t* dims_coord; uint32_t rank_charge; uint32_t rank_coord; int to_flush; } nucleus_t; typedef struct electron_s { FILE* file; uint64_t alpha_num; uint64_t beta_num; int to_flush; } electron_t; typedef struct rdm_s { FILE* file; uint64_t dim_one_e; double* one_e; char* two_e_file_name; int to_flush; } rdm_t; #+end_src *** TO DO - to_flush = 1 in write - to_flush = 0 when flushed - name *** Structs for the text back end #+begin_src c :tangle trexio_text.h typedef struct trexio_text_s { trexio_t parent ; int lock_file; nucleus_t* nucleus; electron_t* electron; rdm_t* rdm; } trexio_text_t; #+end_src *** Init/deinit functions #+begin_src c :tangle trexio_text.h trexio_exit_code trexio_text_init(trexio_t* file); #+end_src #+begin_src c :tangle trexio_text.c trexio_exit_code trexio_text_init(trexio_t* file) { if (file == NULL) return TREXIO_INVALID_ARG_1; trexio_text_t* f = (trexio_text_t*) file; /* If directory doesn't exist, create it in write mode */ struct stat st; if (stat(file->file_name, &st) == 0 && S_ISDIR(st.st_mode)) { /* Do nothing */ } else { if (file->mode == 'r') return TREXIO_READONLY; if (mkdir(file->file_name, 0777) != 0) { return TREXIO_FAILURE; } } /* Create the lock file in the directory */ const char* lock_file_name = "/.lock"; char* file_name = (char*) calloc( strlen(file->file_name) + strlen(lock_file_name) + 1, sizeof(char)); assert (file_name != NULL); strcpy (file_name, file->file_name); strcat (file_name, lock_file_name); f->lock_file = open(file_name,O_WRONLY|O_CREAT|O_TRUNC, 0644); assert (f->lock_file > 0); free(file_name); f->nucleus = NULL; f->electron= NULL; f->rdm = NULL; return TREXIO_SUCCESS; } #+end_src #+begin_src c :tangle trexio_text.h trexio_exit_code trexio_text_lock(trexio_t* file); #+end_src #+begin_src c :tangle trexio_text.c trexio_exit_code trexio_text_lock(trexio_t* file) { if (file == NULL) return TREXIO_INVALID_ARG_1; trexio_text_t* f = (trexio_text_t*) file; struct flock fl; fl.l_type = F_WRLCK; fl.l_whence = SEEK_SET; fl.l_start = 0; fl.l_len = 0; fl.l_pid = getpid(); int rc = fcntl(f->lock_file, F_SETLKW, &fl); if (rc == -1) return TREXIO_FAILURE; return TREXIO_SUCCESS; } #+end_src #+begin_src c :tangle trexio_text.h trexio_exit_code trexio_text_finalize(trexio_t* file); #+end_src #+begin_src c :tangle trexio_text.c trexio_exit_code trexio_text_finalize(trexio_t* file) { if (file == NULL) return TREXIO_INVALID_ARG_1; trexio_exit_code rc; rc = trexio_text_free_nucleus( (trexio_text_t*) file); assert (rc == TREXIO_SUCCESS); rc = trexio_text_free_rdm( (trexio_text_t*) file); assert (rc == TREXIO_SUCCESS); return TREXIO_SUCCESS; } #+end_src #+begin_src c :tangle trexio_text.h trexio_exit_code trexio_text_unlock(trexio_t* file); #+end_src #+begin_src c :tangle trexio_text.c trexio_exit_code trexio_text_unlock(trexio_t* file) { if (file == NULL) return TREXIO_INVALID_ARG_1; trexio_text_t* f = (trexio_text_t*) file; struct flock fl; fl.l_type = F_WRLCK; fl.l_whence = SEEK_SET; fl.l_start = 0; fl.l_len = 0; fl.l_pid = getpid(); fl.l_type = F_UNLCK; fcntl(f->lock_file, F_SETLK, &fl); close(f->lock_file); return TREXIO_SUCCESS; } #+end_src *** Nucleus struct **** Read the struct #+begin_src c :tangle trexio_text.h nucleus_t* trexio_text_read_nucleus(trexio_text_t* file); #+end_src #+begin_src c :tangle trexio_text.c nucleus_t* trexio_text_read_nucleus(trexio_text_t* file) { if (file == NULL) return NULL; if (file->nucleus != NULL) return file->nucleus; /* Allocate the data structure */ nucleus_t* nucleus = (nucleus_t*) malloc(sizeof(nucleus_t)); assert (nucleus != NULL); nucleus->file = NULL; nucleus->num = 0; nucleus->coord = NULL; nucleus->dims_coord = NULL; nucleus->charge = NULL; nucleus->dims_charge = NULL; nucleus->to_flush = 0; /* Try to open the file. If the file does not exist, return */ const char* nucleus_file_name = "/nucleus.txt"; char * file_name = (char*) calloc( strlen(file->parent.file_name) + strlen(nucleus_file_name) + 1, sizeof(char)); assert (file_name != NULL); strcpy (file_name, file->parent.file_name); strcat (file_name, nucleus_file_name); /* If the file exists, read it */ FILE* f = fopen(file_name,"r"); if (f != NULL) { /* Find size of file to allocate the max size of the string buffer */ fseek(f, 0L, SEEK_END); size_t sz = ftell(f); fseek(f, 0L, SEEK_SET); char* buffer = (char*) malloc(sz*sizeof(char)); /* Read the dimensioning variables */ int rc; rc = fscanf(f, "%s", buffer); assert (rc == 1); assert (strcmp(buffer, "rank_charge") == 0); rc = fscanf(f, "%u", &(nucleus->rank_charge)); assert (rc == 1); nucleus->dims_charge = (uint64_t*) calloc(nucleus->rank_charge, sizeof(uint64_t)); assert (nucleus->dims_charge != NULL); uint64_t size_charge = 1; for (uint i=0; irank_charge; i++){ rc = fscanf(f, "%s", buffer); assert (rc == 1); //assert (strcmp(buffer, "dims_charge") == 0); rc = fscanf(f, "%lu", &(nucleus->dims_charge[i])); assert (rc == 1); size_charge *= nucleus->dims_charge[i]; } rc = fscanf(f, "%s", buffer); assert (rc == 1); assert (strcmp(buffer, "rank_coord") == 0); rc = fscanf(f, "%u", &(nucleus->rank_coord)); assert (rc == 1); nucleus->dims_coord = (uint64_t*) calloc(nucleus->rank_coord, sizeof(uint64_t)); assert (nucleus->dims_coord != NULL); uint64_t size_coord = 1; for (uint i=0; irank_coord; i++){ rc = fscanf(f, "%s", buffer); assert (rc == 1); //assert (strcmp(buffer, "dims_coord") == 0); rc = fscanf(f, "%lu", &(nucleus->dims_coord[i])); assert (rc == 1); size_coord *= nucleus->dims_coord[i]; } /* Allocate arrays */ nucleus->charge = (double*) calloc(size_charge, sizeof(double)); assert (nucleus->charge != NULL); nucleus->coord = (double*) calloc(size_coord, sizeof(double)); assert (nucleus->coord != NULL); /* Read data */ rc = fscanf(f, "%s", buffer); assert (rc == 1); assert (strcmp(buffer, "num") == 0); rc = fscanf(f, "%lu", &(nucleus->num)); assert (rc == 1); rc = fscanf(f, "%s", buffer); assert (rc == 1); assert (strcmp(buffer, "charge") == 0); for (uint64_t i=0 ; icharge[i])); assert (rc == 1); } rc = fscanf(f, "%s", buffer); assert (rc == 1); assert (strcmp(buffer, "coord") == 0); for (uint64_t i=0 ; icoord[i])); assert (rc == 1); } free(buffer); fclose(f); f = NULL; } if (file->parent.mode == 'w') { nucleus->file = fopen(file_name,"a"); } else { nucleus->file = fopen(file_name,"r"); } free(file_name); file->nucleus = nucleus; return nucleus; } #+end_src **** Flush the struct #+begin_src c :tangle trexio_text.h trexio_exit_code trexio_text_flush_nucleus(const trexio_text_t* file); #+end_src #+begin_src c :tangle trexio_text.c trexio_exit_code trexio_text_flush_nucleus(const trexio_text_t* file) { if (file == NULL) return TREXIO_INVALID_ARG_1; if (file->parent.mode == 'r') return TREXIO_READONLY; nucleus_t* nucleus = file->nucleus; if (nucleus == NULL) return TREXIO_SUCCESS; if (nucleus->to_flush == 0) return TREXIO_SUCCESS; FILE* f = nucleus->file; assert (f != NULL); rewind(f); /* Write the dimensioning variables */ fprintf(f, "rank_charge %d\n", nucleus->rank_charge); uint64_t size_charge = 1; for (uint i=0; irank_charge; i++){ fprintf(f, "dims_charge[%d] %ld\n", i, nucleus->dims_charge[i]); size_charge *= nucleus->dims_charge[i]; } fprintf(f, "rank_coord %d\n", nucleus->rank_coord); uint64_t size_coord = 1; for (uint i=0; irank_coord; i++){ fprintf(f, "dims_coord[%d] %ld\n", i, nucleus->dims_coord[i]); size_coord *= nucleus->dims_coord[i]; } /* Write arrays */ fprintf(f, "num %ld\n", nucleus->num); fprintf(f, "charge\n"); for (uint64_t i=0 ; icharge[i]); } fprintf(f, "coord\n"); for (uint64_t i=0 ; icoord[i]); } fflush(f); file->nucleus->to_flush = 0; return TREXIO_SUCCESS; } #+end_src **** Free memory Memory is allocated when reading. The following function frees memory. #+begin_src c :tangle trexio_text.h trexio_exit_code trexio_text_free_nucleus(trexio_text_t* file); #+end_src #+begin_src c :tangle trexio_text.c trexio_exit_code trexio_text_free_nucleus(trexio_text_t* file) { if (file == NULL) return TREXIO_INVALID_ARG_1; trexio_exit_code rc; if (file->parent.mode != 'r') { rc = trexio_text_flush_nucleus(file); if (rc != TREXIO_SUCCESS) return TREXIO_FAILURE; } nucleus_t* nucleus = file->nucleus; if (nucleus == NULL) return TREXIO_SUCCESS; if (nucleus->file != NULL) { fclose(nucleus->file); nucleus->file = NULL; } if (nucleus->dims_coord != NULL) { free (nucleus->dims_coord); nucleus->dims_coord = NULL; } if (nucleus->coord != NULL) { free (nucleus->coord); nucleus->coord = NULL; } if (nucleus->dims_charge != NULL) { free (nucleus->dims_charge); nucleus->dims_charge = NULL; } if (nucleus->charge != NULL) { free (nucleus->charge); nucleus->charge = NULL; } free (nucleus); file->nucleus = NULL; return TREXIO_SUCCESS; } #+end_src **** Read/Write the num attribute #+begin_src c :tangle trexio_text.h trexio_exit_code trexio_text_read_nucleus_num(const trexio_t* file, uint64_t* num); trexio_exit_code trexio_text_write_nucleus_num(const trexio_t* file, const uint64_t num); #+end_src #+begin_src c :tangle trexio_text.c trexio_exit_code trexio_text_read_nucleus_num(const trexio_t* file, uint64_t* num) { if (file == NULL) return TREXIO_INVALID_ARG_1; if (num == NULL) return TREXIO_INVALID_ARG_2; nucleus_t* nucleus = trexio_text_read_nucleus((trexio_text_t*) file); if (nucleus == NULL) return TREXIO_FAILURE; /**/ *num = nucleus->num; return TREXIO_SUCCESS; } trexio_exit_code trexio_text_write_nucleus_num(const trexio_t* file, const uint64_t num) { if (file == NULL) return TREXIO_INVALID_ARG_1; if (file->mode == 'r') return TREXIO_READONLY; nucleus_t* nucleus = trexio_text_read_nucleus((trexio_text_t*) file); if (nucleus == NULL) return TREXIO_FAILURE; nucleus->num = num; nucleus->to_flush = 1; return TREXIO_SUCCESS; } #+end_src **** Read/Write the coord attribute The ~coord~ array is assumed allocated with the appropriate size. #+begin_src c :tangle trexio_text.h trexio_exit_code trexio_text_read_nucleus_coord(const trexio_t* file, double* coord, const uint32_t rank, const uint64_t* dims); trexio_exit_code trexio_text_write_nucleus_coord(const trexio_t* file, const double* coord, const uint32_t rank, const uint64_t* dims); #+end_src #+begin_src c :tangle trexio_text.c trexio_exit_code trexio_text_read_nucleus_coord(const trexio_t* file, double* coord, const uint32_t rank, const uint64_t* dims) { if (file == NULL) return TREXIO_INVALID_ARG_1; if (coord == NULL) return TREXIO_INVALID_ARG_2; nucleus_t* nucleus = trexio_text_read_nucleus((trexio_text_t*) file); if (nucleus == NULL) return TREXIO_FAILURE; if (rank != nucleus->rank_coord) return TREXIO_INVALID_ARG_3; uint64_t dim_size = 1; for (uint i=0; idims_coord[i]) return TREXIO_INVALID_ARG_4; dim_size *= dims[i]; } for (uint64_t i=0 ; icoord[i]; } return TREXIO_SUCCESS; } trexio_exit_code trexio_text_write_nucleus_coord(const trexio_t* file, const double* coord, const uint32_t rank, const uint64_t* dims) { if (file == NULL) return TREXIO_INVALID_ARG_1; if (coord == NULL) return TREXIO_INVALID_ARG_2; if (file->mode == 'r') return TREXIO_READONLY; nucleus_t* nucleus = trexio_text_read_nucleus((trexio_text_t*) file); if (nucleus == NULL) return TREXIO_FAILURE; if (nucleus->coord != NULL) { free(nucleus->coord); nucleus->coord = NULL; } if (nucleus->dims_coord != NULL) { free(nucleus->dims_coord); nucleus->dims_coord = NULL; } nucleus->rank_coord = rank; nucleus->dims_coord = (uint64_t*) calloc(rank, sizeof(uint64_t)); uint64_t dim_size = 1; for (uint i=0; irank_coord; i++){ nucleus->dims_coord[i] = dims[i]; dim_size *= dims[i]; } nucleus->coord = (double*) calloc(dim_size, sizeof(double)); for (uint64_t i=0 ; icoord[i] = coord[i]; } nucleus->to_flush = 1; return TREXIO_SUCCESS; } #+end_src **** Read/Write the charge attribute The ~charge~ array is assumed allocated with the appropriate size. #+begin_src c :tangle trexio_text.h trexio_exit_code trexio_text_read_nucleus_charge(const trexio_t* file, double* charge, const uint32_t rank, const uint64_t* dims); trexio_exit_code trexio_text_write_nucleus_charge(const trexio_t* file, const double* charge, const uint32_t rank, const uint64_t* dims); #+end_src #+begin_src c :tangle trexio_text.c trexio_exit_code trexio_text_read_nucleus_charge(const trexio_t* file, double* charge, const uint32_t rank, const uint64_t* dims) { if (file == NULL) return TREXIO_INVALID_ARG_1; if (charge == NULL) return TREXIO_INVALID_ARG_2; nucleus_t* nucleus = trexio_text_read_nucleus((trexio_text_t*) file); if (nucleus == NULL) return TREXIO_FAILURE; if (rank != nucleus->rank_charge) return TREXIO_INVALID_ARG_3; uint64_t dim_size = 1; for (uint i=0; idims_charge[i]) return TREXIO_INVALID_ARG_4; dim_size *= dims[i]; } for (uint64_t i=0 ; icharge[i]; } return TREXIO_SUCCESS; } trexio_exit_code trexio_text_write_nucleus_charge(const trexio_t* file, const double* charge, const uint32_t rank, const uint64_t* dims) { if (file == NULL) return TREXIO_INVALID_ARG_1; if (charge == NULL) return TREXIO_INVALID_ARG_2; if (file->mode == 'r') return TREXIO_READONLY; nucleus_t* nucleus = trexio_text_read_nucleus((trexio_text_t*) file); if (nucleus == NULL) return TREXIO_FAILURE; if (nucleus->charge != NULL) { free(nucleus->charge); nucleus->charge = NULL; } if (nucleus->dims_charge != NULL) { free(nucleus->dims_charge); nucleus->dims_charge = NULL; } nucleus->rank_charge = rank; nucleus->dims_charge = (uint64_t*) calloc(rank, sizeof(uint64_t)); uint64_t dim_size = 1; for (uint i=0; irank_charge; i++){ nucleus->dims_charge[i] = dims[i]; dim_size *= dims[i]; } nucleus->charge = (double*) calloc(dim_size, sizeof(double)); for (uint64_t i=0 ; icharge[i] = charge[i]; } nucleus->to_flush = 1; return TREXIO_SUCCESS; } #+end_src *** RDM struct **** Read the complete struct #+begin_src c :tangle trexio_text.h rdm_t* trexio_text_read_rdm(trexio_text_t* file); #+end_src #+begin_src c :tangle trexio_text.c rdm_t* trexio_text_read_rdm(trexio_text_t* file) { if (file == NULL) return NULL; if (file->rdm != NULL) return file->rdm; /* Allocate the data structure */ rdm_t* rdm = (rdm_t*) malloc(sizeof(rdm_t)); assert (rdm != NULL); rdm->one_e = NULL; rdm->two_e_file_name = NULL; rdm->file = NULL; rdm->to_flush = 0; /* Try to open the file. If the file does not exist, return */ const char* rdm_file_name = "/rdm.txt"; char * file_name = (char*) calloc( strlen(file->parent.file_name) + strlen(rdm_file_name) + 1, sizeof(char)); assert (file_name != NULL); strcpy (file_name, file->parent.file_name); strcat (file_name, rdm_file_name); /* If the file exists, read it */ FILE* f = fopen(file_name,"r"); if (f != NULL) { /* Find size of file to allocate the max size of the string buffer */ fseek(f, 0L, SEEK_END); size_t sz = ftell(f); fseek(f, 0L, SEEK_SET); char* buffer = (char*) malloc(sz*sizeof(char)); /* Read the dimensioning variables */ int rc; rc = fscanf(f, "%s", buffer); assert (rc == 1); assert (strcmp(buffer, "dim_one_e") == 0); rc = fscanf(f, "%lu", &(rdm->dim_one_e)); assert (rc == 1); /* Allocate arrays */ rdm->one_e = (double*) calloc(rdm->dim_one_e, sizeof(double)); assert (rdm->one_e != NULL); /* Read one_e */ rc = fscanf(f, "%s", buffer); assert (rc == 1); assert (strcmp(buffer, "one_e") == 0); for (uint64_t i=0 ; idim_one_e; i++) { rc = fscanf(f, "%lf", &(rdm->one_e[i])); assert (rc == 1); } /* Read two_e */ rc = fscanf(f, "%s", buffer); assert (rc == 1); assert (strcmp(buffer, "two_e_file_name") == 0); rc = fscanf(f, "%s", buffer); assert (rc == 1); rdm->two_e_file_name = (char*) malloc (strlen(buffer)*sizeof(char)); strcpy(rdm->two_e_file_name, buffer); free(buffer); fclose(f); f = NULL; } if (file->parent.mode == 'w') { rdm->file = fopen(file_name,"a"); } else { rdm->file = fopen(file_name,"r"); } free(file_name); file->rdm = rdm ; return rdm; } #+end_src **** Flush the complete struct #+begin_src c :tangle trexio_text.h trexio_exit_code trexio_text_flush_rdm(const trexio_text_t* file); #+end_src #+begin_src c :tangle trexio_text.c trexio_exit_code trexio_text_flush_rdm(const trexio_text_t* file) { if (file == NULL) return TREXIO_INVALID_ARG_1; if (file->parent.mode == 'r') return TREXIO_READONLY; rdm_t* rdm = file->rdm; if (rdm == NULL) return TREXIO_SUCCESS; if (rdm->to_flush == 0) return TREXIO_SUCCESS; FILE* f = rdm->file; assert (f != NULL); rewind(f); /* Write the dimensioning variables */ fprintf(f, "num %ld\n", rdm->dim_one_e); /* Write arrays */ fprintf(f, "one_e\n"); for (uint64_t i=0 ; i< rdm->dim_one_e; i++) { fprintf(f, "%lf\n", rdm->one_e[i]); } fprintf(f, "two_e_file_name\n"); fprintf(f, "%s\n", rdm->two_e_file_name); fflush(f); file->rdm->to_flush = 0; return TREXIO_SUCCESS; } #+end_src **** Free memory Memory is allocated when reading. The followig function frees memory. #+begin_src c :tangle trexio_text.h trexio_exit_code trexio_text_free_rdm(trexio_text_t* file); #+end_src #+begin_src c :tangle trexio_text.c trexio_exit_code trexio_text_free_rdm(trexio_text_t* file) { if (file == NULL) return TREXIO_INVALID_ARG_1; trexio_exit_code rc; if (file->parent.mode != 'r') { rc = trexio_text_flush_rdm(file); if (rc != TREXIO_SUCCESS) return TREXIO_FAILURE; } rdm_t* rdm = file->rdm; if (rdm == NULL) return TREXIO_SUCCESS; if (rdm->file != NULL) { fclose(rdm->file); rdm->file = NULL; } if (rdm->one_e != NULL) { free (rdm->one_e); rdm->one_e = NULL; } if (rdm->two_e_file_name != NULL) { free (rdm->two_e_file_name); rdm->two_e_file_name = NULL; } free (rdm); file->rdm = NULL; return TREXIO_SUCCESS; } #+end_src **** Read/Write the one_e attribute The ~one_e~ array is assumed allocated with the appropriate size. #+begin_src c :tangle trexio_text.h trexio_exit_code trexio_text_read_rdm_one_e(const trexio_t* file, double* one_e, const uint64_t dim_one_e); trexio_exit_code trexio_text_write_rdm_one_e(const trexio_t* file, const double* one_e, const uint64_t dim_one_e); #+end_src #+begin_src c :tangle trexio_text.c trexio_exit_code trexio_text_read_rdm_one_e(const trexio_t* file, double* one_e, const uint64_t dim_one_e) { if (file == NULL) return TREXIO_INVALID_ARG_1; if (one_e == NULL) return TREXIO_INVALID_ARG_2; rdm_t* rdm = trexio_text_read_rdm((trexio_text_t*) file); if (rdm == NULL) return TREXIO_FAILURE; if (dim_one_e != rdm->dim_one_e) return TREXIO_INVALID_ARG_3; for (uint64_t i=0 ; ione_e[i]; } return TREXIO_SUCCESS; } trexio_exit_code trexio_text_write_rdm_one_e(const trexio_t* file, const double* one_e, const uint64_t dim_one_e) { if (file == NULL) return TREXIO_INVALID_ARG_1; if (one_e == NULL) return TREXIO_INVALID_ARG_2; if (file->mode != 'r') return TREXIO_READONLY; rdm_t* rdm = trexio_text_read_rdm((trexio_text_t*) file); if (rdm == NULL) return TREXIO_FAILURE; rdm->dim_one_e = dim_one_e; for (uint64_t i=0 ; ione_e[i] = one_e[i]; } rdm->to_flush = 1; return TREXIO_SUCCESS; } #+end_src **** Read/Write the two_e attribute ~two_e~ is a sparse data structure, which can be too large to fit in memory. So we provide functions to read and write it by chunks. In the text back end, the easiest way to do it is to create a file for each sparse float structure. #+begin_src c :tangle trexio_text.h trexio_exit_code trexio_text_buffered_read_rdm_two_e(const trexio_t* file, const uint64_t offset, const uint64_t size, int64_t* index, double* value); trexio_exit_code trexio_text_buffered_write_rdm_two_e(const trexio_t* file, const uint64_t offset, const uint64_t size, const int64_t* index, const double* value); #+end_src #+begin_src c :tangle trexio_text.c trexio_exit_code trexio_text_buffered_read_rdm_two_e(const trexio_t* file, const uint64_t offset, const uint64_t size, int64_t* index, double* value) { if (file == NULL) return TREXIO_INVALID_ARG_1; if (index == NULL) return TREXIO_INVALID_ARG_4; if (value == NULL) return TREXIO_INVALID_ARG_5; rdm_t* rdm = trexio_text_read_rdm((trexio_text_t*) file); if (rdm == NULL) return TREXIO_FAILURE; FILE* f = fopen(rdm->two_e_file_name, "r"); if (f == NULL) return TREXIO_END; const uint64_t line_length = 64; fseek(f, (long) offset * line_length, SEEK_SET); int rc; for (uint64_t i=0 ; imode != 'r') return TREXIO_READONLY; rdm_t* rdm = trexio_text_read_rdm((trexio_text_t*) file); if (rdm == NULL) return TREXIO_FAILURE; FILE* f = fopen(rdm->two_e_file_name, "w"); if (f == NULL) return TREXIO_FAILURE; const uint64_t line_length = 64; fseek(f, (long) offset * line_length, SEEK_SET); int rc; for (uint64_t i=0 ; i