diff --git a/src/obidmscolumn.c b/src/obidmscolumn.c index 94a354a..0622070 100644 --- a/src/obidmscolumn.c +++ b/src/obidmscolumn.c @@ -32,6 +32,7 @@ #include "obilittlebigman.h" #include "obiblob_indexer.h" #include "utils.h" +#include "libjson/json_utils.h" #define DEBUG_LEVEL 0 // TODO has to be defined somewhere else (cython compil flag?) @@ -931,6 +932,7 @@ OBIDMS_column_p obi_create_column(OBIDMS_p dms, int column_file_descriptor; size_t header_size; size_t data_size; + int comments_ok; index_t minimum_line_count; OBIType_t returned_data_type; OBIType_t stored_data_type; @@ -1146,8 +1148,19 @@ OBIDMS_column_p obi_create_column(OBIDMS_p dms, strncpy(header->name, column_name, OBIDMS_COLUMN_MAX_NAME); - if ((comments != NULL) && (*comments != '\0')) - strncpy(header->comments, comments, COMMENTS_MAX_LENGTH); + // Comments must be a json string, even empty + if ((strcmp(comments, "") == 0) || (comments == NULL)) + comments_ok = obi_column_write_comments(new_column, "{}"); + else + comments_ok = obi_column_write_comments(new_column, comments); + if (comments_ok < 0) + { + obidebug(1, "\nError writing comments in new column"); + munmap(new_column->header, header_size); + close(column_file_descriptor); + free(new_column); + return NULL; + } // Store the associated column reference if needed // TODO discuss cases if (data_type == OBI_QUAL) @@ -1750,6 +1763,46 @@ int obi_enlarge_column(OBIDMS_column_p column) } +int obi_column_write_comments(OBIDMS_column_p column, const char* comments) +{ + if (comments == NULL) + return 0; // TODO or error? or set to empty string? discuss + + if (strlen(comments) > COMMENTS_MAX_LENGTH) + { + obi_set_errno(OBICOL_UNKNOWN_ERROR); + obidebug(1, "\nError: comments too long (maximum length: %d, length: %lu, comments: %s", + COMMENTS_MAX_LENGTH, strlen(comments), comments); + return -1; + } + + strcpy((column->header)->comments, comments); + + return 0; +} + + +int obi_column_add_comment(OBIDMS_column_p column, const char* key, const char* value) +{ + char* new_comments = NULL; + + new_comments = obi_add_comment((column->header)->comments, key, value); + if (new_comments == NULL) + { + obidebug(1, "\nError adding a comment in a column, key: %s, value: %s", key, value); + return -1; + } + + if (obi_column_write_comments(column, new_comments) < 0) + { + obidebug(1, "\nError adding a comment in a column, key: %s, value: %s", key, value); + return -1; + } + + return 0; +} + + void obi_set_column_to_value(OBIDMS_column_p column, index_t first_line_nb, index_t nb_lines, @@ -2067,7 +2120,7 @@ int obi_clean_unfinished_columns(OBIDMS_p dms) struct dirent* dms_dirent; struct dirent* col_dirent; DIR* col_dir; - int i,j; + size_t i,j; char* column_file_path; char* column_dir_path; char* col_name; diff --git a/src/obidmscolumn.h b/src/obidmscolumn.h index 9ff83a7..4b76c79 100644 --- a/src/obidmscolumn.h +++ b/src/obidmscolumn.h @@ -38,7 +38,7 @@ */ #define MAXIMUM_LINE_COUNT (1000000000) /**< The maximum line count for the data of a column (1E9). //TODO */ -#define COMMENTS_MAX_LENGTH (2048) /**< The maximum length for comments. +#define COMMENTS_MAX_LENGTH (4096) /**< The maximum length for comments. */ #define FORMATTED_ELT_NAMES_SEPARATOR '\0' /**< The separator between elements names once formatted to be stored in columns. */ @@ -256,7 +256,7 @@ size_t obi_calculate_header_size(index_t nb_elements_per_line, int64_t elts_name * If NULL or "", the indexer name is set as the column name. * @param associated_column_name The name of the associated column if there is one (otherwise NULL or ""). * @param associated_column_version The version of the associated column if there is one (otherwise -1). - * @param comments Optional comments associated with the column (NULL or "" if no comments associated). + * @param comments Optional comments associated with the column in JSON format (NULL, "" or "{}" if no comments associated). * * @returns A pointer on the newly created column structure. * @retval NULL if an error occurred. @@ -372,6 +372,43 @@ int obi_truncate_column(OBIDMS_column_p column); int obi_enlarge_column(OBIDMS_column_p column); +/** + * @brief Writes comments to a column file. + * + * @warning This overwrites any other previous comments. + * + * @param column A pointer on an OBIDMS column. + * @param comments A character string containing the comments. + * + * @retval 0 if the operation was successfully completed. + * @retval -1 if an error occurred. + * + * @since August 2018 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +int obi_column_write_comments(OBIDMS_column_p column, const char* comments); + + +/** + * @brief Adds comments to a column file. + * + * This reads the comments in the JSON format and adds the key value pair. + * If the key already exists, the value format is turned to array and the new value is appended + * if it is not already in the array. + * + * @param column A pointer on an OBIDMS column. + * @param key The key. + * @param value The value associated with the key. + * + * @retval 0 if the operation was successfully completed. + * @retval -1 if an error occurred. + * + * @since August 2018 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +int obi_column_add_comment(OBIDMS_column_p column, const char* key, const char* value); + + /* * @brief Sets the data in a column to the specified value. *