commit 2ea5b1880382e72eb995ad13ef53295caf65ed93
parent 631c84414d0fe0204349f5c6d8336cf047fbccb9
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Mon, 23 May 2022 10:50:33 +0200
[De]serialize the isotope metadata
Add the shtr_isotope_metadata_write, and
shtr_isotope_metadata_create_from_stream function.
Diffstat:
2 files changed, 275 insertions(+), 3 deletions(-)
diff --git a/src/shtr.h b/src/shtr.h
@@ -85,7 +85,7 @@ struct shtr_line {
* isotopic index read from the HITRAN file. The original value is in [0, 9]
* with 0 actually meaning 10. Thus, once decoded, the index is located in
* [1, 10]. The next member variable simply stores this index but decremented
- * by one in order to make it compatible with C indexeing. As a result, it
+ * by one in order to make it compatible with C indexing. As a result, it
* can be used directly to index the 'isotopes' array of a 'shtr_molecule'
* data structure loaded from an isotope metadata file */
int32_t isotope_id_local;
@@ -188,6 +188,14 @@ shtr_isotope_metadata_load_stream
const char* stream_name, /* NULL <=> use default stream name */
struct shtr_isotope_metadata** metadata);
+/* Load the isotope metadata serialized with the "shtr_isotope_metadata_write"
+ * function */
+SHTR_API res_T
+shtr_isotope_metadata_create_from_stream
+ (struct shtr* shtr,
+ FILE* stream,
+ struct shtr_isotope_metadata** metadata);
+
SHTR_API res_T
shtr_isotope_metadata_ref_get
(struct shtr_isotope_metadata* metadata);
@@ -219,6 +227,11 @@ shtr_isotope_metadata_find_molecule
const int molecule_id, /* Unique identifier of the molecule <=> Global index */
struct shtr_molecule* molecule);
+SHTR_API res_T
+shtr_isotope_metadata_write
+ (const struct shtr_isotope_metadata* metadata,
+ FILE* stream);
+
/*******************************************************************************
* Lines API
******************************************************************************/
diff --git a/src/shtr_isotope_metadata.c b/src/shtr_isotope_metadata.c
@@ -24,8 +24,7 @@
#include "shtr_param.h"
#include <rsys/cstr.h>
-#include <rsys/dynamic_array.h>
-#include <rsys/hash_table.h>
+#include <rsys/dynamic_array_char.h>
#include <rsys/ref_count.h>
#include <rsys/str.h>
#include <rsys/text_reader.h>
@@ -33,6 +32,11 @@
#include <ctype.h>
#include <string.h>
+/* Version of the isotope metadata. One should increment it and perform a
+ * version management onto serialized data when the isotope metadata structure
+ * are updated. */
+static const int SHTR_ISOTOPE_METADATA_VERSION = 0;
+
/* Generate the dynamic array of isotopes */
#define DARRAY_NAME isotope
#define DARRAY_DATA struct shtr_isotope
@@ -456,6 +460,172 @@ error:
goto exit;
}
+static res_T
+write_molecules
+ (const struct shtr_isotope_metadata* metadata,
+ const char* caller,
+ FILE* stream)
+{
+ const struct molecule* molecules = NULL;
+ size_t i, nmolecules;
+ res_T res = RES_OK;
+ ASSERT(metadata && caller && stream);
+
+ molecules = darray_molecule_cdata_get(&metadata->molecules);
+ nmolecules = darray_molecule_size_get(&metadata->molecules);
+
+ #define WRITE(Var, Nb) { \
+ if(fwrite((Var), sizeof(*(Var)), (Nb), stream) != (Nb)) { \
+ res = RES_IO_ERR; \
+ goto error; \
+ } \
+ } (void)0
+ WRITE(&nmolecules, 1);
+
+ FOR_EACH(i, 0, nmolecules) {
+ const struct molecule* molecule = molecules + i;
+ const size_t len = str_len(&molecule->name);
+ WRITE(&len, 1);
+ WRITE(str_cget(&molecule->name), len);
+ WRITE(molecule->isotopes_range, 2);
+ WRITE(&molecule->id, 1);
+ }
+ #undef WRITE
+
+exit:
+ return res;
+error:
+ log_err(metadata->shtr, "%s: error writing molecules\n", caller);
+ goto exit;
+}
+
+static res_T
+read_molecules
+ (struct shtr_isotope_metadata* metadata,
+ const char* caller,
+ FILE* stream)
+{
+ struct darray_char name;
+ struct molecule* molecules = NULL;
+ size_t i, nmolecules;
+ res_T res = RES_OK;
+ ASSERT(metadata && caller && stream);
+
+ darray_char_init(metadata->shtr->allocator, &name);
+
+ #define READ(Var, Nb) { \
+ if(fread((Var), sizeof(*(Var)), (Nb), stream) != (Nb)) { \
+ if(feof(stream)) { \
+ res = RES_BAD_ARG; \
+ } else if(ferror(stream)) { \
+ res = RES_IO_ERR; \
+ } else { \
+ res = RES_UNKNOWN_ERR; \
+ } \
+ goto error; \
+ } \
+ } (void)0
+
+ READ(&nmolecules, 1);
+
+ res = darray_molecule_resize(&metadata->molecules, nmolecules);
+ if(res != RES_OK) goto error;
+
+ molecules = darray_molecule_data_get(&metadata->molecules);
+ FOR_EACH(i, 0, nmolecules) {
+ struct molecule* molecule = molecules + i;
+ size_t len = 0;
+
+ READ(&len, 1);
+ res = darray_char_resize(&name, len+1);
+ if(res != RES_OK) goto error;
+
+ READ(darray_char_data_get(&name), len);
+ darray_char_data_get(&name)[len] = '\0';
+ res = str_set(&molecule->name, darray_char_data_get(&name));
+ if(res != RES_OK) goto error;
+
+ READ(molecule->isotopes_range, 2);
+ READ(&molecule->id, 1);
+ }
+ #undef READ
+
+exit:
+ darray_char_release(&name);
+ return res;
+error:
+ log_err(metadata->shtr, "%s: error reading molecules -- %s.\n",
+ caller, res_to_cstr(res));
+ goto exit;
+}
+
+static res_T
+write_isotopes
+ (const struct shtr_isotope_metadata* metadata,
+ const char* caller,
+ FILE* stream)
+{
+ const struct shtr_isotope* isotopes = NULL;
+ size_t nisotopes = 0;
+ res_T res = RES_OK;
+ ASSERT(metadata && caller && stream);
+
+ isotopes = darray_isotope_cdata_get(&metadata->isotopes);
+ nisotopes = darray_isotope_size_get(&metadata->isotopes);
+
+ #define WRITE(Var, Nb) { \
+ if(fwrite((Var), sizeof(*(Var)), (Nb), stream) != (Nb)) { \
+ log_err(metadata->shtr, "%s: error writing isotopes\n", caller); \
+ res = RES_IO_ERR; \
+ goto error; \
+ } \
+ } (void)0
+ WRITE(&nisotopes, 1);
+ WRITE(isotopes, nisotopes);
+ #undef WRITE
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+read_isotopes
+ (struct shtr_isotope_metadata* metadata,
+ const char* caller,
+ FILE* stream)
+{
+ size_t nisotopes = 0;
+ res_T res = RES_OK;
+ ASSERT(metadata && caller && stream);
+
+ #define READ(Var, Nb) { \
+ if(fread((Var), sizeof(*(Var)), (Nb), stream) != (Nb)) { \
+ if(feof(stream)) { \
+ res = RES_BAD_ARG; \
+ } else if(ferror(stream)) { \
+ res = RES_IO_ERR; \
+ } else { \
+ res = RES_UNKNOWN_ERR; \
+ } \
+ goto error; \
+ } \
+ } (void)0
+ READ(&nisotopes, 1);
+ res = darray_isotope_resize(&metadata->isotopes, nisotopes);
+ if(res != RES_OK) goto error;
+ READ(darray_isotope_data_get(&metadata->isotopes), nisotopes);
+ #undef READ
+
+exit:
+ return res;
+error:
+ log_err(metadata->shtr, "%s: error reading isotopes -- %s.\n",
+ caller, res_to_cstr(res));
+ goto exit;
+}
+
static void
release_isotope_metadata(ref_T* ref)
{
@@ -517,6 +687,61 @@ shtr_isotope_metadata_load_stream
}
res_T
+shtr_isotope_metadata_create_from_stream
+ (struct shtr* shtr,
+ FILE* stream,
+ struct shtr_isotope_metadata** out_metadata)
+{
+ struct shtr_isotope_metadata* metadata = NULL;
+ int version = 0;
+ res_T res = RES_OK;
+
+ if(!shtr || !out_metadata || !stream) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ res = create_isotope_metadata(shtr, &metadata);
+ if(res != RES_OK) goto error;
+
+ #define READ(Var, Nb) { \
+ if(fread((Var), sizeof(*(Var)), (Nb), stream) != (Nb)) { \
+ if(feof(stream)) { \
+ res = RES_BAD_ARG; \
+ } else if(ferror(stream)) { \
+ res = RES_IO_ERR; \
+ } else { \
+ res = RES_UNKNOWN_ERR; \
+ } \
+ goto error; \
+ } \
+ } (void)0
+ READ(&version, 1);
+ if(version != SHTR_ISOTOPE_METADATA_VERSION) {
+ log_err(shtr,
+ "%s: unexpected isotope metadata version %d. "
+ "Experting a isotope metadata in version %d.\n",
+ FUNC_NAME, version, SHTR_ISOTOPE_METADATA_VERSION);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ res = read_molecules(metadata, FUNC_NAME, stream);
+ if(res != RES_OK) goto error;
+ res = read_isotopes(metadata, FUNC_NAME, stream);
+ if(res != RES_OK) goto error;
+
+ READ(metadata->molid2idx, SHTR_MAX_MOLECULES_COUNT);
+ #undef READ
+
+exit:
+ if(out_metadata) *out_metadata = metadata;
+ return res;
+error:
+ goto exit;
+}
+
+res_T
shtr_isotope_metadata_ref_get
(struct shtr_isotope_metadata* metadata)
{
@@ -617,3 +842,37 @@ error:
goto exit;
}
+res_T
+shtr_isotope_metadata_write
+ (const struct shtr_isotope_metadata* metadata,
+ FILE* stream)
+{
+ res_T res = RES_OK;
+
+ if(!metadata || !stream) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ #define WRITE(Var, Nb) { \
+ if(fwrite((Var), sizeof(*(Var)), (Nb), stream) != (Nb)) { \
+ log_err(metadata->shtr, "%s: error writing metadata\n", FUNC_NAME); \
+ res = RES_IO_ERR; \
+ goto error; \
+ } \
+ } (void)0
+ WRITE(&SHTR_ISOTOPE_METADATA_VERSION, 1);
+
+ res = write_molecules(metadata, FUNC_NAME, stream);
+ if(res != RES_OK) goto error;
+ res = write_isotopes(metadata, FUNC_NAME, stream);
+ if(res != RES_OK) goto error;
+
+ WRITE(metadata->molid2idx, SHTR_MAX_MOLECULES_COUNT);
+ #undef WRITE
+
+exit:
+ return res;
+error:
+ goto exit;
+}