diff --git a/python/obitools3/obidms/_obidms.cfiles b/python/obitools3/obidms/_obidms.cfiles index 1428221..b5b7b4f 100644 --- a/python/obitools3/obidms/_obidms.cfiles +++ b/python/obitools3/obidms/_obidms.cfiles @@ -1,5 +1,7 @@ ../../../src/obidms.h ../../../src/obidms.c +../../../src/obiview.h +../../../src/obiview.c ../../../src/obidmscolumn.h ../../../src/obidmscolumn.c ../../../src/obidmscolumndir.h @@ -15,4 +17,6 @@ ../../../src/obiavl.h ../../../src/obiavl.c ../../../src/encode.h -../../../src/encode.c \ No newline at end of file +../../../src/encode.c +../../../src/obidmscolumn_idx.h +../../../src/obidmscolumn_idx.c diff --git a/python/obitools3/obidms/_obidms.pxd b/python/obitools3/obidms/_obidms.pxd index 7093304..653e5cd 100644 --- a/python/obitools3/obidms/_obidms.pxd +++ b/python/obitools3/obidms/_obidms.pxd @@ -2,52 +2,80 @@ from .capi.obidms cimport OBIDMS_p from .capi.obidmscolumn cimport OBIDMS_column_p +from .capi.obiview cimport Obiview_p from .capi.obitypes cimport obiversion_t, OBIType_t, index_t -cdef class OBIDMS_column - - -cdef class OBIDMS: - - cdef OBIDMS_p pointer - cdef str dms_name - - cpdef dict list(self) - cpdef close(self) - cpdef OBIDMS_column open_column(self, - str column_name, - bint create=*, - bint clone=*, bint clone_data=*, - bint referring=*, - obiversion_t version_number=*, - str type=*, - index_t nb_lines=*, - index_t nb_elements_per_line=*, - list elements_names=*, - str avl_name=*, - str comments=*) - - cdef class OBIDMS_column: - cdef OBIDMS_column_p pointer + cdef OBIDMS_column_p* pointer cdef OBIDMS dms + cdef Obiview_p view cdef str data_type cdef str dms_name cdef str column_name cdef index_t nb_elements_per_line cdef list elements_names - - cpdef OBIDMS_column_p referred_column_pointer - -# cpdef object get_item(self, index_t line_nb, str element_name) TODO can't declare because not the same in all subclasses -# cpdef set_item(self, index_t line_nb, str element_name, object value) TODO can't declare because object value - cpdef grep_line(self, index_t line_nb) + + cpdef update_pointer(self) cpdef list get_elements_names(self) cpdef str get_data_type(self) cpdef index_t get_nb_lines_used(self) cpdef str get_creation_date(self) cpdef str get_comments(self) cpdef close(self) + @staticmethod + cdef object get_subclass_type(OBIDMS_column_p column_p) + + +cdef class OBIDMS_column_multi_elts(OBIDMS_column): + + cpdef set_line(self, index_t line_nb, dict values) + + +cdef class OBIDMS_column_line: + + cdef OBIDMS_column column + cdef index_t index + + +cdef class OBIView: + + cdef Obiview_p pointer + cdef str name + cdef dict columns + cdef dict columns_pp # TODO this dict might be unnecessary + cdef OBIDMS dms + + cpdef delete_column(self, str column_name) + cpdef add_column(self, + str column_name, + obiversion_t version_number=*, + str type=*, + index_t nb_lines=*, + index_t nb_elements_per_line=*, + list elements_names=*, + str avl_name=*, + str comments=*, + bint create=* + ) + cpdef select_line(self, index_t line_nb) + cpdef select_lines(self, list line_selection) + cpdef save_and_close(self) + + +cdef class OBIView_line : + + cdef index_t index + cdef OBIView view + + +cdef class OBIDMS: + + cdef OBIDMS_p pointer + cdef str dms_name + + cpdef close(self) + cpdef OBIView open_view(self, str view_name) + cpdef OBIView new_view(self, str view_name, object view_to_clone=*, list line_selection=*) diff --git a/python/obitools3/obidms/_obidms.pyx b/python/obitools3/obidms/_obidms.pyx index 3478d6c..918ae57 100644 --- a/python/obitools3/obidms/_obidms.pyx +++ b/python/obitools3/obidms/_obidms.pyx @@ -6,16 +6,12 @@ from obitools3.utils cimport bytes2str, str2bytes from .capi.obidms cimport obi_dms, \ obi_close_dms -from .capi.obidmscolumn cimport obi_column_get_header_from_name, \ - obi_unmap_header, \ - obi_column_get_latest_version_from_name, \ - obi_create_column, \ - obi_clone_column, \ - obi_open_column, \ - obi_close_column, \ + +from .capi.obidmscolumn cimport obi_truncate_and_close_column, \ obi_column_format_date, \ - obi_grep_line, \ + OBIDMS_column_p, \ OBIDMS_column_header_p + from .capi.obitypes cimport const_char_p, \ OBIType_t, \ OBI_INT, \ @@ -24,42 +20,486 @@ from .capi.obitypes cimport const_char_p, \ OBI_CHAR, \ OBI_STR, \ OBI_SEQ, \ - name_data_type + name_data_type, \ + only_ATGC # discuss - from ._obidms cimport OBIDMS from ._obidms cimport OBIDMS_column +from ._obidms cimport OBIView_line from ._obidmscolumn_int cimport OBIDMS_column_int, \ - OBIDMS_column_int_writable, \ - OBIDMS_column_int_multi_elts, \ - OBIDMS_column_int_multi_elts_writable + OBIDMS_column_multi_elts_int from ._obidmscolumn_float cimport OBIDMS_column_float, \ - OBIDMS_column_float_writable, \ - OBIDMS_column_float_multi_elts, \ - OBIDMS_column_float_multi_elts_writable + OBIDMS_column_multi_elts_float from ._obidmscolumn_bool cimport OBIDMS_column_bool, \ - OBIDMS_column_bool_writable, \ - OBIDMS_column_bool_multi_elts, \ - OBIDMS_column_bool_multi_elts_writable + OBIDMS_column_multi_elts_bool from ._obidmscolumn_char cimport OBIDMS_column_char, \ - OBIDMS_column_char_writable, \ - OBIDMS_column_char_multi_elts, \ - OBIDMS_column_char_multi_elts_writable + OBIDMS_column_multi_elts_char from ._obidmscolumn_str cimport OBIDMS_column_str, \ - OBIDMS_column_str_writable, \ - OBIDMS_column_str_multi_elts, \ - OBIDMS_column_str_multi_elts_writable + OBIDMS_column_multi_elts_str from ._obidmscolumn_seq cimport OBIDMS_column_seq, \ - OBIDMS_column_seq_writable, \ - OBIDMS_column_seq_multi_elts, \ - OBIDMS_column_seq_multi_elts_writable + OBIDMS_column_multi_elts_seq +from ._obidms cimport OBIView, OBIView_line + +from .capi.obiview cimport Obiview_p, \ + obi_new_view, \ + obi_new_view_cloned_from_name, \ + obi_open_view, \ + obi_view_delete_column, \ + obi_view_add_column, \ + obi_view_get_column, \ + obi_view_get_pointer_on_column_in_view, \ + obi_select_line, \ + obi_select_lines, \ + obi_save_and_close_view + +from libc.stdlib cimport malloc +from cpython.pycapsule cimport PyCapsule_New, PyCapsule_GetPointer + + +cdef class OBIDMS_column : + + # Should only be initialized through a subclass + def __init__(self, OBIView view, str column_name): + + cdef OBIDMS_column_p column_p + cdef OBIDMS_column_p* column_pp + + column_pp = PyCapsule_GetPointer(((view.columns_pp)[column_name]), NULL) # or use C function + column_p = column_pp[0] # TODO ugly cython dereferencing but can't find better + + # Fill structure + self.pointer = column_pp + self.dms = view.dms + self.view = view.pointer # TODO pointer or instance? + self.data_type = bytes2str(name_data_type((column_p.header).returned_data_type)) + self.column_name = bytes2str((column_p.header).name) + self.nb_elements_per_line = (column_p.header).nb_elements_per_line + self.elements_names = (bytes2str((column_p.header).elements_names)).split(';') + + def __setitem__(self, index_t line_nb, object value): + self.set_line(line_nb, value) + + def __getitem__(self, index_t line_nb): + return self.get_line(line_nb) + + def __len__(self): + return (self.pointer)[0].header.lines_used + + def __sizeof__(self): + return ((self.pointer)[0].header.header_size + (self.pointer)[0].header.data_size) + + def __iter__(self): + + # Declarations + cdef index_t lines_used + cdef index_t line_nb + + # Yield each line + lines_used = (self.pointer)[0].header.lines_used + for line_nb in range(lines_used): + yield self.get_line(line_nb) + + cpdef update_pointer(self): + self.pointer = obi_view_get_pointer_on_column_in_view(self.view, str2bytes(self.column_name)) + + cpdef list get_elements_names(self): + return self.elements_names + + cpdef str get_data_type(self): + return self.data_type + + cpdef index_t get_nb_lines_used(self): + return (self.pointer)[0].header.lines_used + + cpdef str get_creation_date(self): + return bytes2str(obi_column_format_date((self.pointer)[0].header.creation_date)) + + cpdef str get_comments(self): + return bytes2str((self.pointer)[0].header.comments) + + def __repr__(self) : + cdef str to_print + to_print = '' + for line in self : + to_print = to_print + str(line) + "\n" + return to_print + + cpdef close(self): + if obi_truncate_and_close_column((self.pointer)[0]) < 0 : + raise Exception("Problem closing a column") + + + @staticmethod + cdef object get_subclass_type(OBIDMS_column_p column_p) : + + cdef object subclass + cdef OBIDMS_column_header_p header + cdef OBIType_t col_type + cdef bint col_writable + cdef bint col_one_element_per_line + + header = column_p.header + col_type = header.returned_data_type + col_writable = column_p.writable + col_one_element_per_line = ((header.nb_elements_per_line) == 1) + + if col_type == OBI_INT : + if col_one_element_per_line : + subclass = OBIDMS_column_int + else : + subclass = OBIDMS_column_multi_elts_int + elif col_type == OBI_FLOAT : + if col_one_element_per_line : + subclass = OBIDMS_column_float + else : + subclass = OBIDMS_column_multi_elts_float + elif col_type == OBI_BOOL : + if col_one_element_per_line : + subclass = OBIDMS_column_bool + else : + subclass = OBIDMS_column_multi_elts_bool + elif col_type == OBI_CHAR : + if col_one_element_per_line : + subclass = OBIDMS_column_char + else : + subclass = OBIDMS_column_multi_elts_char + elif col_type == OBI_STR : + if col_one_element_per_line : + subclass = OBIDMS_column_str + else : + subclass = OBIDMS_column_multi_elts_str + elif col_type == OBI_SEQ : + if col_one_element_per_line : + subclass = OBIDMS_column_seq + else : + subclass = OBIDMS_column_multi_elts_seq + else : + raise Exception("Problem with the data type") + + return subclass + + +###################################################################################################### + +cdef class OBIDMS_column_multi_elts(OBIDMS_column) : + + def __getitem__(self, index_t line_nb): + return OBIDMS_column_line(self, line_nb) + + cpdef set_line(self, index_t line_nb, dict values): + for element_name in values : + self.set_item(line_nb, element_name, values[element_name]) + +###################################################################################################### + +cdef class OBIDMS_column_line : + + def __init__(self, OBIDMS_column column, index_t line_nb) : + self.index = line_nb + self.column = column + + def __getitem__(self, str element_name) : + return self.column.get_item(self.index, element_name) + + def __setitem__(self, str element_name, object value): + self.column.set_item(self.index, element_name, value) + + def __contains__(self, str element_name): + return (element_name in self.column.elements_names) + + def __repr__(self) : + return str(self.column.get_line(self.index)) + +########################################## + + +cdef class OBIView : + + def __init__(self, OBIDMS dms, str view_name, bint new=False, object view_to_clone=None, list line_selection=None): + + cdef Obiview_p view = NULL + cdef int i + cdef list col_list + cdef str col_name + cdef OBIDMS_column column + cdef OBIDMS_column_p column_p + cdef OBIDMS_column_p* column_pp + cdef OBIDMS_column_header_p header + cdef index_t* line_selection_p + + self.dms = dms + + if line_selection is not None : + line_selection_p = malloc((len(line_selection) + 1) * sizeof(index_t)) + for i in range(len(line_selection)) : + line_selection_p[i] = line_selection[i] # TODO type problem? + print(line_selection_p[i], line_selection[i]) + line_selection_p[len(line_selection)] = -1 + else : + line_selection_p = NULL + + if new : + if view_to_clone is not None : + if type(view_to_clone) == str : + view = obi_new_view_cloned_from_name(dms.pointer, str2bytes(view_name), str2bytes(view_to_clone), line_selection_p) + else : + view = obi_new_view(dms.pointer, str2bytes(view_name), ( view_to_clone).pointer, line_selection_p) + elif view_to_clone is None : + view = obi_new_view(dms.pointer, str2bytes(view_name), NULL, line_selection_p) + elif not new : + if view_name is not None : + view = obi_open_view(dms.pointer, str2bytes(view_name)) + elif view_name is None : + view = obi_open_view(dms.pointer, NULL) + + if view == NULL : + raise Exception("Error creating/opening view") + + self.pointer = view + self.name = bytes2str(view.name) + + # go through columns to build list and open python object (TODO make separate function?) + self.columns = {} + self.columns_pp = {} + + i = 0 + while i < view.column_count : + column_pp = ((view.columns)+i) + column_p = (view.columns)[i] + header = (column_p).header + + col_name = bytes2str(header.name) + col_capsule = PyCapsule_New(column_pp, NULL, NULL) # TODO discuss + (self.columns_pp)[col_name] = col_capsule + + subclass = OBIDMS_column.get_subclass_type(column_p) + self.columns[col_name] = subclass(self, col_name) + + i+=1 + + + def __repr__(self) : + + cdef str s + cdef OBIDMS_column column + cdef OBIDMS_column_p column_p + + s = self.name + s = s + ", " + str(self.pointer.line_count) + " lines" + for column_name in self.columns : # TODO make function in OBIDMS_column class + column = self.columns[column_name] + column_p = (column.pointer)[0] + s = s + "\n" + column_name + ", version " + str(column_p.header.version) + ", data type: " + column.data_type + return s + + + cpdef delete_column(self, str column_name) : + + cdef int i + cdef Obiview_p view + cdef OBIDMS_column column + cdef OBIDMS_column_p column_p + cdef OBIDMS_column_p* column_pp + cdef OBIDMS_column_header_p header + cdef str column_n + + view = self.pointer + + if obi_view_delete_column(view, str2bytes(column_name)) < 0 : + raise Exception("Problem deleting a column from a view") + + # Update the dictionaries of column pointers and column objects, and update pointers in column objects (make function?): + (self.columns).pop(column_name) + (self.columns_pp).pop(column_name) + + i = 0 + while i < view.column_count : + column_pp = ((view.columns)+i) + column_p = (view.columns)[i] + header = (column_p).header + col_name = bytes2str(header.name) + col_capsule = PyCapsule_New(column_pp, NULL, NULL) + (self.columns_pp)[col_name] = col_capsule + i+=1 + + for column_n in self.columns : + (self.columns[column_n]).update_pointer() + + + cpdef add_column(self, + str column_name, + obiversion_t version_number=-1, + str type='', + index_t nb_lines=0, + index_t nb_elements_per_line=1, # TODO 1? + list elements_names=None, + str avl_name="default_AVL_tree", + str comments="", + bint create=True # TODO + ) : + + cdef bytes column_name_b + cdef bytes elements_names_b + cdef object subclass + cdef OBIDMS_column_p* column_pp + cdef OBIDMS_column_p column_p + + column_name_b = str2bytes(column_name) + + if nb_elements_per_line > 1 : + elements_names_b = str2bytes(';'.join(elements_names)) + elif nb_elements_per_line == 1 : + elements_names_b = column_name_b + + if type : + if type == 'OBI_INT' : + data_type = OBI_INT + elif type == 'OBI_FLOAT' : + data_type = OBI_FLOAT + elif type == 'OBI_BOOL' : + data_type = OBI_BOOL + elif type == 'OBI_CHAR' : + data_type = OBI_CHAR + elif type == 'OBI_STR' : + data_type = OBI_STR + elif type == 'OBI_SEQ' : + data_type = OBI_SEQ + else : + raise Exception("Invalid provided data type") + + if (obi_view_add_column(self.pointer, column_name_b, version_number, # should return pointer on column? + data_type, nb_lines, nb_elements_per_line, + elements_names_b, str2bytes(avl_name), + str2bytes(comments), create) < 0) : + raise Exception("Problem adding a column in a view") + + # Store the column pointer + + column_pp = obi_view_get_pointer_on_column_in_view(self.pointer, column_name_b) + if column_pp == NULL : + raise Exception("Problem getting a column in a view") + + col_capsule = PyCapsule_New(column_pp, NULL, NULL) # TODO + (self.columns_pp)[column_name] = col_capsule + + # Open and store the subclass + column_p = column_pp[0] # TODO ugly cython dereferencing + subclass = OBIDMS_column.get_subclass_type(column_p) + (self.columns)[column_name] = subclass(self, column_name) + + + cpdef save_and_close(self) : + if (obi_save_and_close_view(self.pointer) < 0) : + raise Exception("Problem closing a view") + + + def __iter__(self): + # iter on each line of all columns + + # Declarations + cdef index_t lines_used + cdef index_t line_nb + cdef OBIView_line line + + # Yield each line TODO line class + lines_used = (self.pointer).line_count + + for line_nb in range(lines_used) : + line = self[line_nb] + yield line + + + def __getitem__(self, object item) : + if type(item) == str : + return (self.columns)[item] + elif type(item) == int : # TODO int? + return OBIView_line(self, item) + + + cpdef select_line(self, index_t line_nb) : + if obi_select_line(self.pointer, line_nb) < 0 : + raise Exception("Problem selecting a line") + + + cpdef select_lines(self, list line_selection) : + cdef index_t* line_selection_p + line_selection_p = malloc((len(line_selection) + 1) * sizeof(index_t)) + for i in range(len(line_selection)) : + line_selection_p[i] = line_selection[i] # TODO type problem? + line_selection_p[len(line_selection)] = -1 + if obi_select_lines(self.pointer, line_selection_p) < 0 : + raise Exception("Problem selecting a list of lines") + + + def __contains__(self, str column_name): + return (column_name in self.columns) + + + def __str__(self) : + cdef OBIView_line line + cdef str to_print + to_print = "" + for line in self.__iter__() : + to_print = to_print + str(line) + "\n" + return to_print + +############################################# + +cdef class OBIView_line : + + def __init__(self, OBIView view, index_t line_nb) : + self.index = line_nb + self.view = view + + def __getitem__(self, str column_name) : + return ((self.view).columns)[column_name][self.index] + + def __setitem__(self, str column_name, object value): + # TODO detect multiple elements (dict type)? put somewhere else? but more risky (in get) + cdef type value_type + cdef str value_obitype + if column_name not in self.view : + if value == None : + raise Exception("Trying to create a column from a None value (can't guess type)") + value_type = type(value) + if value_type == int : + value_obitype = 'OBI_INT' + elif value_type == float : + value_obitype = 'OBI_FLOAT' + elif value_type == bool : + value_obitype = 'OBI_BOOL' + elif value_type == str : + if only_ATGC(str2bytes(value)) : # TODO + value_obitype = 'OBI_SEQ' + elif len(value) == 1 : + value_obitype = 'OBI_CHAR' + elif (len(value) > 1) : + value_obitype = 'OBI_STR' + else : + raise Exception("Could not guess the type of a value to create a new column") + self.view.add_column(column_name, type=value_obitype) + + (((self.view).columns)[column_name]).set_line(self.index, value) + + def __contains__(self, str column_name): + return (column_name in self.view) + + def __repr__(self): + cdef dict line + cdef str column_name + line = {} + for column_name in self.view.columns : + line[column_name] = self[column_name] + return str(line) + +########################################## cdef class OBIDMS : @@ -81,310 +521,12 @@ cdef class OBIDMS : cpdef close(self) : if (obi_close_dms(self.pointer)) < 0 : raise Exception("Problem closing an OBIDMS") - - - cpdef dict list(self): # TDODO This is a temporary function that will be rewritten - - # Declarations - cdef object p - cdef dict dms = {} - cdef str column_name - cdef bytes column_name_b - cdef str data_type - cdef str creation_date - cdef obiversion_t latest_version - cdef index_t line_count - cdef OBIDMS_column_header_p header - - p = Path(self.dms_name+'.obidms') - - print("{:<30} {:<12} {:<25} {:<30} {:<40}".format('-Column name-', - '-Data type-', - '-Latest version number-', - '-Line count of latest version-', - '-Creation date of latest version-')) - for entry in p.iterdir(): - if entry.suffix == ".obicol": - column_name = entry.stem - column_name_b = str2bytes(column_name) - dms[column_name] = {} - header = obi_column_get_header_from_name(self.pointer, column_name_b, -1) - data_type = bytes2str(name_data_type(header.returned_data_type)) - line_count = header.line_count - creation_date = bytes2str(obi_column_format_date(header.creation_date)) - obi_unmap_header(header) - latest_version = obi_column_get_latest_version_from_name(self.pointer, column_name_b) - dms[column_name]['data_type'] = data_type - dms[column_name]['latest_version'] = latest_version - dms[column_name]['line_count'] = line_count - dms[column_name]['creation_date'] = creation_date - print("{:<30} {:<12} {:<25} {:<30} {:<40}".format(column_name, data_type, latest_version, line_count, creation_date)) - - return dms - - cpdef OBIDMS_column open_column(self, - str column_name, - bint create=False, - bint clone=False, bint clone_data=True, - bint referring=False, - obiversion_t version_number=-1, - str type='', - index_t nb_lines=0, - index_t nb_elements_per_line=0, - list elements_names=None, - str avl_name="default_AVL_tree", - str comments=""): - - # Declarations - cdef OBIDMS_column column - cdef object subclass # TODO object? - cdef bytes column_name_b - cdef OBIDMS_column_header_p header - cdef OBIType_t data_type - - header = NULL - - # Format the character string to send to C function - column_name_b = str2bytes(column_name) - - # Get the header of the latest version of the column if - # some needed informations are not provided - if ((not type or not nb_elements_per_line) and not create) : - header = obi_column_get_header_from_name(self.pointer, column_name_b, version_number) - - # Get the data type if not provided - if not type : - if create : - raise Exception("A data type must be specified") - else : - data_type = header.returned_data_type - else : - if type == 'OBI_INT' : - data_type = OBI_INT - elif type == 'OBI_FLOAT' : - data_type = OBI_FLOAT - elif type == 'OBI_BOOL' : - data_type = OBI_BOOL - elif type == 'OBI_CHAR' : - data_type = OBI_CHAR - elif type == 'OBI_STR' : - data_type = OBI_STR - elif type == 'OBI_SEQ' : - data_type = OBI_SEQ - else : - raise Exception("Invalid provided data type") - - # Get the number of elements per line if not provided and needed - if not nb_elements_per_line : - if create : # Set to one if not provided (default value) - nb_elements_per_line = 1 - else : - nb_elements_per_line = header.returned_nb_elements_per_line - if nb_elements_per_line > 1 : - elements_names = bytes2str(header.elements_names).split(';') - - if header != NULL : - obi_unmap_header(header) # TODO check if error? but C will already warn and there's nothing to do - - # Open the column with the right subclass depending on the data type, the mode - # (read-only or writable) and whether there are multiple elements per line or not - if data_type == OBI_INT : - if (create or clone) : - if nb_elements_per_line == 1 : - subclass = OBIDMS_column_int_writable - else : - subclass = OBIDMS_column_int_multi_elts_writable - else : - if nb_elements_per_line == 1 : - subclass = OBIDMS_column_int - else : - subclass = OBIDMS_column_int_multi_elts - elif data_type == OBI_FLOAT : - if (create or clone) : - if nb_elements_per_line == 1 : - subclass = OBIDMS_column_float_writable - else : - subclass = OBIDMS_column_float_multi_elts_writable - else : - if nb_elements_per_line == 1 : - subclass = OBIDMS_column_float - else : - subclass = OBIDMS_column_float_multi_elts - elif data_type == OBI_BOOL : - if (create or clone) : - if nb_elements_per_line == 1 : - subclass = OBIDMS_column_bool_writable - else : - subclass = OBIDMS_column_bool_multi_elts_writable - else : - if nb_elements_per_line == 1 : - subclass = OBIDMS_column_bool - else : - subclass = OBIDMS_column_bool_multi_elts - elif data_type == OBI_CHAR : - if (create or clone) : - if nb_elements_per_line == 1 : - subclass = OBIDMS_column_char_writable - else : - subclass = OBIDMS_column_char_multi_elts_writable - else : - if nb_elements_per_line == 1 : - subclass = OBIDMS_column_char - else : - subclass = OBIDMS_column_char_multi_elts - elif data_type == OBI_STR : - if (create or clone) : - if nb_elements_per_line == 1 : - subclass = OBIDMS_column_str_writable - else : - subclass = OBIDMS_column_str_multi_elts_writable - else : - if nb_elements_per_line == 1 : - subclass = OBIDMS_column_str - else : - subclass = OBIDMS_column_str_multi_elts - elif data_type == OBI_SEQ : - if (create or clone) : - if nb_elements_per_line == 1 : - subclass = OBIDMS_column_seq_writable - else : - subclass = OBIDMS_column_seq_multi_elts_writable - else : - if nb_elements_per_line == 1 : - subclass = OBIDMS_column_seq - else : - subclass = OBIDMS_column_seq_multi_elts - else : - raise Exception("Problem with the data type") - - column = subclass(self, column_name, - create, clone, clone_data, - referring, - version_number, data_type, - nb_lines, nb_elements_per_line, - elements_names, avl_name, - comments) - - return column - - - -cdef class OBIDMS_column : - - # Should only be initialized through a subclass - def __init__(self, - OBIDMS dms, - str column_name, - bint create, - bint clone, bint clone_data, - bint referring, - obiversion_t version_number, - OBIType_t type, - index_t nb_lines, - index_t nb_elements_per_line, - list elements_names, - str avl_name, - str comments): - - # Declarations - cdef bytes column_name_b - cdef bytes dms_name_b - cdef bytes avl_name_b - cdef bytes elements_names_b - cdef bytes comments_b - - # Fill structure - self.dms = dms - self.data_type = bytes2str(name_data_type(type)) - self.column_name = column_name - self.nb_elements_per_line = nb_elements_per_line - self.elements_names = elements_names - - # Format the character strings to send them to C functions - column_name_b = str2bytes(column_name) - dms_name_b = str2bytes(self.dms.dms_name) - avl_name_b = str2bytes(avl_name) - comments_b = str2bytes(comments) - - # Create, clone or open column - if create : - if elements_names == None : - elements_names_b = column_name_b - else : - elements_names_b = str2bytes(";".join(elements_names)) - self.pointer = obi_create_column(self.dms.pointer, column_name_b, type, - nb_lines, nb_elements_per_line, - elements_names_b, avl_name_b, comments_b, - referring) - else : - if clone : - self.pointer = obi_clone_column(self.dms.pointer, column_name_b, version_number, referring, clone_data) - elif referring : - self.pointer = obi_clone_column(self.dms.pointer, column_name_b, version_number, referring, False) - referred_column_pointer = self.pointer.referred_column - else : - self.pointer = obi_open_column(self.dms.pointer, column_name_b, version_number) - - - def __len__(self): - return self.pointer.header.lines_used - - def __sizeof__(self): - return (self.pointer.header.header_size + self.pointer.header.data_size) - - - def __iter__(self): - - # Declarations - cdef index_t lines_used - cdef index_t line_nb - - # Yield each line - lines_used = self.pointer.header.lines_used - for line_nb in range(lines_used): - yield self.get_line(line_nb) + cpdef OBIView open_view(self, str view_name) : + return OBIView(self, view_name) + + + cpdef OBIView new_view(self, str view_name, object view_to_clone=None, list line_selection=None) : + return OBIView(self, view_name, new=True, view_to_clone=view_to_clone, line_selection=line_selection) - - def __setitem__(self, index_t line_nb, object value): - self.set_line(line_nb, value) - - - def __getitem__(self, index_t line_nb): - return self.get_line(line_nb) - - -# cpdef object get_item(self, index_t line_nb, str element_name): TODO -# raise NotImplementedError - - -# cpdef set_item(self, index_t line_nb, str element_name, object value): TODO -# raise NotImplementedError - - cpdef grep_line(self, index_t line_nb): - if obi_grep_line(self.pointer, line_nb) < 0 : - raise Exception("Error grepping line") - - cpdef list get_elements_names(self): - return self.elements_names - - - cpdef str get_data_type(self): - return self.data_type - - - cpdef index_t get_nb_lines_used(self): - return self.pointer.header.lines_used - - - cpdef str get_creation_date(self): - return bytes2str(obi_column_format_date(self.pointer.header.creation_date)) - - cpdef str get_comments(self): - return bytes2str(self.pointer.header.comments) - - cpdef close(self): - raise NotImplementedError - - diff --git a/python/obitools3/obidms/_obidmscolumn_bool.cfiles b/python/obitools3/obidms/_obidmscolumn_bool.cfiles index c96979c..c0ce92d 100644 --- a/python/obitools3/obidms/_obidmscolumn_bool.cfiles +++ b/python/obitools3/obidms/_obidmscolumn_bool.cfiles @@ -1,5 +1,7 @@ ../../../src/obidmscolumn_bool.c ../../../src/obidmscolumn_bool.h +../../../src/obiview.h +../../../src/obiview.c ../../../src/obidmscolumn.h ../../../src/obidmscolumn.c ../../../src/obidmscolumndir.h diff --git a/python/obitools3/obidms/_obidmscolumn_bool.pxd b/python/obitools3/obidms/_obidmscolumn_bool.pxd index f07ae93..7fd3985 100644 --- a/python/obitools3/obidms/_obidmscolumn_bool.pxd +++ b/python/obitools3/obidms/_obidmscolumn_bool.pxd @@ -1,25 +1,14 @@ #cython: language_level=3 -from .capi.obitypes cimport obibool_t, index_t -from ._obidms cimport OBIDMS_column +from .capi.obitypes cimport index_t +from ._obidms cimport OBIDMS_column, OBIDMS_column_multi_elts cdef class OBIDMS_column_bool(OBIDMS_column): cpdef object get_line(self, index_t line_nb) cpdef set_line(self, index_t line_nb, object value) - cpdef close(self) -cdef class OBIDMS_column_bool_writable(OBIDMS_column_bool): - cpdef set_line(self, index_t line_nb, object value) - cpdef close(self) - -cdef class OBIDMS_column_bool_multi_elts(OBIDMS_column_bool): +cdef class OBIDMS_column_multi_elts_bool(OBIDMS_column_multi_elts): cpdef object get_item(self, index_t line_nb, str element_name) cpdef object get_line(self, index_t line_nb) - cpdef set_item(self, index_t line_nb, str element_name, obibool_t value) - cpdef set_line(self, index_t line_nb, object values) - -cdef class OBIDMS_column_bool_multi_elts_writable(OBIDMS_column_bool_multi_elts): - cpdef set_item(self, index_t line_nb, str element_name, obibool_t value) - cpdef set_line(self, index_t line_nb, object values) - cpdef close(self) + cpdef set_item(self, index_t line_nb, str element_name, object value) diff --git a/python/obitools3/obidms/_obidmscolumn_bool.pyx b/python/obitools3/obidms/_obidmscolumn_bool.pyx index 8bc04b8..b0fe60c 100644 --- a/python/obitools3/obidms/_obidmscolumn_bool.pyx +++ b/python/obitools3/obidms/_obidmscolumn_bool.pyx @@ -1,13 +1,12 @@ #cython: language_level=3 -from .capi.obidmscolumn cimport obi_close_column,\ - obi_truncate_and_close_column, \ - obi_column_get_obibool_with_elt_name, \ - obi_column_get_obibool_with_elt_idx, \ - obi_column_set_obibool_with_elt_name, \ - obi_column_set_obibool_with_elt_idx +from .capi.obidmscolumn cimport obi_truncate_and_close_column, \ + obi_column_get_obibool_with_elt_name_in_view, \ + obi_column_get_obibool_with_elt_idx_in_view, \ + obi_column_set_obibool_with_elt_name_in_view, \ + obi_column_set_obibool_with_elt_idx_in_view from .capi.obierrno cimport obi_errno -from .capi.obitypes cimport OBIBool_NA +from .capi.obitypes cimport OBIBool_NA, obibool_t from obitools3.utils cimport str2bytes @@ -19,7 +18,7 @@ cdef class OBIDMS_column_bool(OBIDMS_column): cpdef object get_line(self, index_t line_nb): cdef obibool_t value cdef object result - value = obi_column_get_obibool_with_elt_idx(self.pointer, line_nb, 0) + value = obi_column_get_obibool_with_elt_idx_in_view(self.view, (self.pointer)[0], line_nb, 0) if obi_errno > 0 : raise IndexError(line_nb) if value == OBIBool_NA : @@ -27,32 +26,20 @@ cdef class OBIDMS_column_bool(OBIDMS_column): else : result = PyBool_FromLong(value) return result - - cpdef set_line(self, index_t line_nb, object value): - raise Exception("Column is read-only") - cpdef close(self): - if obi_close_column(self.pointer) < 0 : - raise Exception("Problem closing a column") - - -cdef class OBIDMS_column_bool_writable(OBIDMS_column_bool): - cpdef set_line(self, index_t line_nb, object value): - if obi_column_set_obibool_with_elt_idx(self.pointer, line_nb, 0, value) < 0: + if value is None : + value = OBIBool_NA + if obi_column_set_obibool_with_elt_idx_in_view(self.view, (self.pointer)[0], line_nb, 0, value) < 0: raise Exception("Problem setting a value in a column") - cpdef close(self): - if obi_truncate_and_close_column(self.pointer) < 0 : - raise Exception("Problem closing a column") - -cdef class OBIDMS_column_bool_multi_elts(OBIDMS_column_bool): +cdef class OBIDMS_column_multi_elts_bool(OBIDMS_column_multi_elts): cpdef object get_item(self, index_t line_nb, str element_name): cdef obibool_t value cdef object result - value = obi_column_get_obibool_with_elt_name(self.pointer, line_nb, str2bytes(element_name)) + value = obi_column_get_obibool_with_elt_name_in_view(self.view, (self.pointer)[0], line_nb, str2bytes(element_name)) if obi_errno > 0 : raise IndexError(line_nb, element_name) if value == OBIBool_NA : @@ -63,42 +50,29 @@ cdef class OBIDMS_column_bool_multi_elts(OBIDMS_column_bool): cpdef object get_line(self, index_t line_nb) : cdef obibool_t value - cdef object result + cdef object value_in_result + cdef dict result cdef index_t i cdef bint all_NA result = {} all_NA = True for i in range(self.nb_elements_per_line) : - value = obi_column_get_obibool_with_elt_idx(self.pointer, line_nb, i) + value = obi_column_get_obibool_with_elt_idx_in_view(self.view, (self.pointer)[0], line_nb, i) if obi_errno > 0 : - raise IndexError(line_nb) - result[self.elements_names[i]] = PyBool_FromLong(value) - if all_NA and (value != OBIBool_NA) : + raise IndexError(line_nb) + if value == OBIBool_NA : + value_in_result = None + else : + value_in_result = PyBool_FromLong(value) + result[self.elements_names[i]] = value_in_result + if all_NA and (value_in_result is not None) : all_NA = False if all_NA : result = None return result - cpdef set_item(self, index_t line_nb, str element_name, obibool_t value): - raise Exception("Column is read-only") - - cpdef set_line(self, index_t line_nb, object values): - raise Exception("Column is read-only") - - -cdef class OBIDMS_column_bool_multi_elts_writable(OBIDMS_column_bool_multi_elts): - - cpdef set_item(self, index_t line_nb, str element_name, obibool_t value): - if obi_column_set_obibool_with_elt_name(self.pointer, line_nb, str2bytes(element_name), value) < 0: + cpdef set_item(self, index_t line_nb, str element_name, object value): + if value is None : + value = OBIBool_NA + if obi_column_set_obibool_with_elt_name_in_view(self.view, (self.pointer)[0], line_nb, str2bytes(element_name), value) < 0: raise Exception("Problem setting a value in a column") - - cpdef set_line(self, index_t line_nb, object values): - cdef obibool_t value - for element_name in values : - value = values[element_name] - self.set_item(line_nb, element_name, value) - - cpdef close(self): - if obi_truncate_and_close_column(self.pointer) < 0 : - raise Exception("Problem closing a column") - diff --git a/python/obitools3/obidms/_obidmscolumn_char.cfiles b/python/obitools3/obidms/_obidmscolumn_char.cfiles index 25f9a80..381f1e0 100644 --- a/python/obitools3/obidms/_obidmscolumn_char.cfiles +++ b/python/obitools3/obidms/_obidmscolumn_char.cfiles @@ -1,5 +1,7 @@ ../../../src/obidmscolumn_char.c ../../../src/obidmscolumn_char.h +../../../src/obiview.h +../../../src/obiview.c ../../../src/obidmscolumn.h ../../../src/obidmscolumn.c ../../../src/obidmscolumndir.h diff --git a/python/obitools3/obidms/_obidmscolumn_char.pxd b/python/obitools3/obidms/_obidmscolumn_char.pxd index 51c7051..515100f 100644 --- a/python/obitools3/obidms/_obidmscolumn_char.pxd +++ b/python/obitools3/obidms/_obidmscolumn_char.pxd @@ -1,25 +1,14 @@ #cython: language_level=3 -from .capi.obitypes cimport obichar_t, index_t -from ._obidms cimport OBIDMS_column +from .capi.obitypes cimport index_t +from ._obidms cimport OBIDMS_column, OBIDMS_column_multi_elts cdef class OBIDMS_column_char(OBIDMS_column): cpdef object get_line(self, index_t line_nb) cpdef set_line(self, index_t line_nb, object value) - cpdef close(self) -cdef class OBIDMS_column_char_writable(OBIDMS_column_char): - cpdef set_line(self, index_t line_nb, object value) - cpdef close(self) - -cdef class OBIDMS_column_char_multi_elts(OBIDMS_column_char): +cdef class OBIDMS_column_multi_elts_char(OBIDMS_column_multi_elts): cpdef object get_item(self, index_t line_nb, str element_name) cpdef object get_line(self, index_t line_nb) - cpdef set_item(self, index_t line_nb, str element_name, str value) - cpdef set_line(self, index_t line_nb, object values) - -cdef class OBIDMS_column_char_multi_elts_writable(OBIDMS_column_char_multi_elts): - cpdef set_item(self, index_t line_nb, str element_name, str value) - cpdef set_line(self, index_t line_nb, object values) - cpdef close(self) + cpdef set_item(self, index_t line_nb, str element_name, object value) diff --git a/python/obitools3/obidms/_obidmscolumn_char.pyx b/python/obitools3/obidms/_obidmscolumn_char.pyx index d8141eb..391cbcb 100644 --- a/python/obitools3/obidms/_obidmscolumn_char.pyx +++ b/python/obitools3/obidms/_obidmscolumn_char.pyx @@ -1,13 +1,12 @@ #cython: language_level=3 -from .capi.obidmscolumn cimport obi_close_column,\ - obi_truncate_and_close_column, \ - obi_column_get_obichar_with_elt_name, \ - obi_column_get_obichar_with_elt_idx, \ - obi_column_set_obichar_with_elt_name, \ - obi_column_set_obichar_with_elt_idx +from .capi.obidmscolumn cimport obi_truncate_and_close_column, \ + obi_column_get_obichar_with_elt_name_in_view, \ + obi_column_get_obichar_with_elt_idx_in_view, \ + obi_column_set_obichar_with_elt_name_in_view, \ + obi_column_set_obichar_with_elt_idx_in_view from .capi.obierrno cimport obi_errno -from .capi.obitypes cimport OBIChar_NA +from .capi.obitypes cimport OBIChar_NA, obichar_t from obitools3.utils cimport str2bytes, bytes2str @@ -17,7 +16,7 @@ cdef class OBIDMS_column_char(OBIDMS_column): cpdef object get_line(self, index_t line_nb): cdef obichar_t value cdef object result - value = obi_column_get_obichar_with_elt_idx(self.pointer, line_nb, 0) + value = obi_column_get_obichar_with_elt_idx_in_view(self.view, (self.pointer)[0], line_nb, 0) if obi_errno > 0 : raise IndexError(line_nb) if value == OBIChar_NA : @@ -27,30 +26,18 @@ cdef class OBIDMS_column_char(OBIDMS_column): return result cpdef set_line(self, index_t line_nb, object value): - raise Exception("Column is read-only") - - cpdef close(self): - if obi_close_column(self.pointer) < 0 : - raise Exception("Problem closing a column") - - -cdef class OBIDMS_column_char_writable(OBIDMS_column_char): - - cpdef set_line(self, index_t line_nb, object value): - if obi_column_set_obichar_with_elt_idx(self.pointer, line_nb, 0, str2bytes(value)[0]) < 0: + if value is None : + value = OBIChar_NA + if obi_column_set_obichar_with_elt_idx_in_view(self.view, (self.pointer)[0], line_nb, 0, str2bytes(value)[0]) < 0: raise Exception("Problem setting a value in a column") - cpdef close(self): - if obi_truncate_and_close_column(self.pointer) < 0 : - raise Exception("Problem closing a column") - -cdef class OBIDMS_column_char_multi_elts(OBIDMS_column_char): +cdef class OBIDMS_column_multi_elts_char(OBIDMS_column_multi_elts): cpdef object get_item(self, index_t line_nb, str element_name): cdef obichar_t value cdef object result - value = obi_column_get_obichar_with_elt_name(self.pointer, line_nb, str2bytes(element_name)) + value = obi_column_get_obichar_with_elt_name_in_view(self.view, (self.pointer)[0], line_nb, str2bytes(element_name)) if obi_errno > 0 : raise IndexError(line_nb, element_name) if value == OBIChar_NA : @@ -58,45 +45,33 @@ cdef class OBIDMS_column_char_multi_elts(OBIDMS_column_char): else : result = bytes2str(value) return result - + cpdef object get_line(self, index_t line_nb) : cdef obichar_t value - cdef object result + cdef object value_in_result + cdef dict result cdef index_t i cdef bint all_NA result = {} all_NA = True for i in range(self.nb_elements_per_line) : - value = obi_column_get_obichar_with_elt_idx(self.pointer, line_nb, i) + value = obi_column_get_obichar_with_elt_idx_in_view(self.view, (self.pointer)[0], line_nb, i) if obi_errno > 0 : - raise IndexError(line_nb) - result[self.elements_names[i]] = bytes2str(value) - if all_NA and (value != OBIChar_NA) : + raise IndexError(line_nb) + if value == OBIChar_NA : + value_in_result = None + else : + value_in_result = bytes2str(value) + result[self.elements_names[i]] = value_in_result + if all_NA and (value_in_result is not None) : all_NA = False if all_NA : result = None return result - cpdef set_item(self, index_t line_nb, str element_name, str value): - raise Exception("Column is read-only") - - cpdef set_line(self, index_t line_nb, object values): - raise Exception("Column is read-only") - - -cdef class OBIDMS_column_char_multi_elts_writable(OBIDMS_column_char_multi_elts): - - cpdef set_item(self, index_t line_nb, str element_name, str value): - if obi_column_set_obichar_with_elt_name(self.pointer, line_nb, str2bytes(element_name), str2bytes(value)[0]) < 0: + cpdef set_item(self, index_t line_nb, str element_name, object value): + if value is None : + value = OBIChar_NA + if obi_column_set_obichar_with_elt_name_in_view(self.view, (self.pointer)[0], line_nb, str2bytes(element_name), str2bytes(value)[0]) < 0: raise Exception("Problem setting a value in a column") - - cpdef set_line(self, index_t line_nb, object values): - cdef str value - for element_name in values : - value = values[element_name] - self.set_item(line_nb, element_name, value) - - cpdef close(self): - if obi_truncate_and_close_column(self.pointer) < 0 : - raise Exception("Problem closing a column") diff --git a/python/obitools3/obidms/_obidmscolumn_float.cfiles b/python/obitools3/obidms/_obidmscolumn_float.cfiles index 3878e83..baf7e74 100644 --- a/python/obitools3/obidms/_obidmscolumn_float.cfiles +++ b/python/obitools3/obidms/_obidmscolumn_float.cfiles @@ -1,5 +1,7 @@ ../../../src/obidmscolumn_float.c ../../../src/obidmscolumn_float.h +../../../src/obiview.h +../../../src/obiview.c ../../../src/obidmscolumn.h ../../../src/obidmscolumn.c ../../../src/obidmscolumndir.h diff --git a/python/obitools3/obidms/_obidmscolumn_float.pxd b/python/obitools3/obidms/_obidmscolumn_float.pxd index e14d9c1..2121ccd 100644 --- a/python/obitools3/obidms/_obidmscolumn_float.pxd +++ b/python/obitools3/obidms/_obidmscolumn_float.pxd @@ -1,25 +1,14 @@ #cython: language_level=3 -from .capi.obitypes cimport obifloat_t, index_t -from ._obidms cimport OBIDMS_column +from .capi.obitypes cimport index_t +from ._obidms cimport OBIDMS_column, OBIDMS_column_multi_elts cdef class OBIDMS_column_float(OBIDMS_column): cpdef object get_line(self, index_t line_nb) cpdef set_line(self, index_t line_nb, object value) - cpdef close(self) -cdef class OBIDMS_column_float_writable(OBIDMS_column_float): - cpdef set_line(self, index_t line_nb, object value) - cpdef close(self) - -cdef class OBIDMS_column_float_multi_elts(OBIDMS_column_float): +cdef class OBIDMS_column_multi_elts_float(OBIDMS_column_multi_elts): cpdef object get_item(self, index_t line_nb, str element_name) cpdef object get_line(self, index_t line_nb) - cpdef set_item(self, index_t line_nb, str element_name, obifloat_t value) - cpdef set_line(self, index_t line_nb, object values) - -cdef class OBIDMS_column_float_multi_elts_writable(OBIDMS_column_float_multi_elts): - cpdef set_item(self, index_t line_nb, str element_name, obifloat_t value) - cpdef set_line(self, index_t line_nb, object values) - cpdef close(self) + cpdef set_item(self, index_t line_nb, str element_name, object value) diff --git a/python/obitools3/obidms/_obidmscolumn_float.pyx b/python/obitools3/obidms/_obidmscolumn_float.pyx index e7516ac..2783e76 100644 --- a/python/obitools3/obidms/_obidmscolumn_float.pyx +++ b/python/obitools3/obidms/_obidmscolumn_float.pyx @@ -1,13 +1,12 @@ #cython: language_level=3 -from .capi.obidmscolumn cimport obi_close_column,\ - obi_truncate_and_close_column, \ - obi_column_get_obifloat_with_elt_name, \ - obi_column_get_obifloat_with_elt_idx, \ - obi_column_set_obifloat_with_elt_name, \ - obi_column_set_obifloat_with_elt_idx +from .capi.obidmscolumn cimport obi_truncate_and_close_column,\ + obi_column_get_obifloat_with_elt_name_in_view, \ + obi_column_get_obifloat_with_elt_idx_in_view, \ + obi_column_set_obifloat_with_elt_name_in_view, \ + obi_column_set_obifloat_with_elt_idx_in_view from .capi.obierrno cimport obi_errno -from .capi.obitypes cimport OBIFloat_NA +from .capi.obitypes cimport OBIFloat_NA, obifloat_t from obitools3.utils cimport str2bytes @@ -17,7 +16,7 @@ cdef class OBIDMS_column_float(OBIDMS_column): cpdef object get_line(self, index_t line_nb): cdef obifloat_t value cdef object result - value = obi_column_get_obifloat_with_elt_idx(self.pointer, line_nb, 0) + value = obi_column_get_obifloat_with_elt_idx_in_view(self.view, (self.pointer)[0], line_nb, 0) if obi_errno > 0 : raise IndexError(line_nb) if value == OBIFloat_NA : @@ -27,30 +26,18 @@ cdef class OBIDMS_column_float(OBIDMS_column): return result cpdef set_line(self, index_t line_nb, object value): - raise Exception("Column is read-only") - - cpdef close(self): - if obi_close_column(self.pointer) < 0 : - raise Exception("Problem closing a column") - - -cdef class OBIDMS_column_float_writable(OBIDMS_column_float): - - cpdef set_line(self, index_t line_nb, object value): - if obi_column_set_obifloat_with_elt_idx(self.pointer, line_nb, 0, value) < 0: + if value is None : + value = OBIFloat_NA + if obi_column_set_obifloat_with_elt_idx_in_view(self.view, (self.pointer)[0], line_nb, 0, value) < 0: raise Exception("Problem setting a value in a column") - cpdef close(self): - if obi_truncate_and_close_column(self.pointer) < 0 : - raise Exception("Problem closing a column") - -cdef class OBIDMS_column_float_multi_elts(OBIDMS_column_float): +cdef class OBIDMS_column_multi_elts_float(OBIDMS_column_multi_elts): cpdef object get_item(self, index_t line_nb, str element_name): cdef obifloat_t value cdef object result - value = obi_column_get_obifloat_with_elt_name(self.pointer, line_nb, str2bytes(element_name)) + value = obi_column_get_obifloat_with_elt_name_in_view(self.view, (self.pointer)[0], line_nb, str2bytes(element_name)) if obi_errno > 0 : raise IndexError(line_nb, element_name) if value == OBIFloat_NA : @@ -58,46 +45,33 @@ cdef class OBIDMS_column_float_multi_elts(OBIDMS_column_float): else : result = value return result - + cpdef object get_line(self, index_t line_nb) : cdef obifloat_t value - cdef object result + cdef object value_in_result + cdef dict result cdef index_t i cdef bint all_NA result = {} all_NA = True for i in range(self.nb_elements_per_line) : - value = obi_column_get_obifloat_with_elt_idx(self.pointer, line_nb, i) + value = obi_column_get_obifloat_with_elt_idx_in_view(self.view, (self.pointer)[0], line_nb, i) if obi_errno > 0 : - raise IndexError(line_nb) - result[self.elements_names[i]] = value - if all_NA and (value != OBIFloat_NA) : + raise IndexError(line_nb) + if value == OBIFloat_NA : + value_in_result = None + else : + value_in_result = value + result[self.elements_names[i]] = value_in_result + if all_NA and (value_in_result is not None) : all_NA = False if all_NA : result = None return result - - cpdef set_item(self, index_t line_nb, str element_name, obifloat_t value): - raise Exception("Column is read-only") - - cpdef set_line(self, index_t line_nb, object values): - raise Exception("Column is read-only") - - -cdef class OBIDMS_column_float_multi_elts_writable(OBIDMS_column_float_multi_elts): - - cpdef set_item(self, index_t line_nb, str element_name, obifloat_t value): - if obi_column_set_obifloat_with_elt_name(self.pointer, line_nb, str2bytes(element_name), value) < 0: + + cpdef set_item(self, index_t line_nb, str element_name, object value): + if value is None : + value = OBIFloat_NA + if obi_column_set_obifloat_with_elt_name_in_view(self.view, (self.pointer)[0], line_nb, str2bytes(element_name), value) < 0: raise Exception("Problem setting a value in a column") - - cpdef set_line(self, index_t line_nb, object values): - cdef obifloat_t value - for element_name in values : - value = values[element_name] - self.set_item(line_nb, element_name, value) - - cpdef close(self): - if obi_truncate_and_close_column(self.pointer) < 0 : - raise Exception("Problem closing a column") - \ No newline at end of file diff --git a/python/obitools3/obidms/_obidmscolumn_int.cfiles b/python/obitools3/obidms/_obidmscolumn_int.cfiles index 6a303aa..35fb144 100644 --- a/python/obitools3/obidms/_obidmscolumn_int.cfiles +++ b/python/obitools3/obidms/_obidmscolumn_int.cfiles @@ -1,5 +1,7 @@ ../../../src/obidmscolumn_int.c ../../../src/obidmscolumn_int.h +../../../src/obiview.h +../../../src/obiview.c ../../../src/obidmscolumn.h ../../../src/obidmscolumn.c ../../../src/obidmscolumndir.h diff --git a/python/obitools3/obidms/_obidmscolumn_int.pxd b/python/obitools3/obidms/_obidmscolumn_int.pxd index ebe9bcd..4bc6711 100644 --- a/python/obitools3/obidms/_obidmscolumn_int.pxd +++ b/python/obitools3/obidms/_obidmscolumn_int.pxd @@ -1,25 +1,14 @@ #cython: language_level=3 -from .capi.obitypes cimport obiint_t, index_t -from ._obidms cimport OBIDMS_column +from .capi.obitypes cimport index_t +from ._obidms cimport OBIDMS_column, OBIDMS_column_multi_elts cdef class OBIDMS_column_int(OBIDMS_column): cpdef object get_line(self, index_t line_nb) cpdef set_line(self, index_t line_nb, object value) - cpdef close(self) -cdef class OBIDMS_column_int_writable(OBIDMS_column_int): - cpdef set_line(self, index_t line_nb, object value) - cpdef close(self) - -cdef class OBIDMS_column_int_multi_elts(OBIDMS_column_int): +cdef class OBIDMS_column_multi_elts_int(OBIDMS_column_multi_elts): cpdef object get_item(self, index_t line_nb, str element_name) cpdef object get_line(self, index_t line_nb) - cpdef set_item(self, index_t line_nb, str element_name, obiint_t value) - cpdef set_line(self, index_t line_nb, object values) - -cdef class OBIDMS_column_int_multi_elts_writable(OBIDMS_column_int_multi_elts): - cpdef set_item(self, index_t line_nb, str element_name, obiint_t value) - cpdef set_line(self, index_t line_nb, object values) - cpdef close(self) + cpdef set_item(self, index_t line_nb, str element_name, object value) diff --git a/python/obitools3/obidms/_obidmscolumn_int.pyx b/python/obitools3/obidms/_obidmscolumn_int.pyx index ff8d013..4fcfaa5 100644 --- a/python/obitools3/obidms/_obidmscolumn_int.pyx +++ b/python/obitools3/obidms/_obidmscolumn_int.pyx @@ -1,13 +1,12 @@ #cython: language_level=3 -from .capi.obidmscolumn cimport obi_close_column,\ - obi_truncate_and_close_column, \ - obi_column_get_obiint_with_elt_name, \ - obi_column_get_obiint_with_elt_idx, \ - obi_column_set_obiint_with_elt_name, \ - obi_column_set_obiint_with_elt_idx +from .capi.obidmscolumn cimport obi_truncate_and_close_column, \ + obi_column_get_obiint_with_elt_name_in_view, \ + obi_column_get_obiint_with_elt_idx_in_view, \ + obi_column_set_obiint_with_elt_name_in_view, \ + obi_column_set_obiint_with_elt_idx_in_view from .capi.obierrno cimport obi_errno -from .capi.obitypes cimport OBIInt_NA +from .capi.obitypes cimport OBIInt_NA, obiint_t from obitools3.utils cimport str2bytes @@ -19,7 +18,7 @@ cdef class OBIDMS_column_int(OBIDMS_column): cpdef object get_line(self, index_t line_nb): cdef obiint_t value cdef object result - value = obi_column_get_obiint_with_elt_idx(self.pointer, line_nb, 0) + value = obi_column_get_obiint_with_elt_idx_in_view(self.view, (self.pointer)[0], line_nb, 0) if obi_errno > 0 : raise IndexError(line_nb) if value == OBIInt_NA : @@ -27,32 +26,20 @@ cdef class OBIDMS_column_int(OBIDMS_column): else : result = PyInt_FromLong(value) return result - + cpdef set_line(self, index_t line_nb, object value): - raise Exception("Column is read-only") - - cpdef close(self): - if obi_close_column(self.pointer) < 0 : - raise Exception("Problem closing a column") - - -cdef class OBIDMS_column_int_writable(OBIDMS_column_int): - - cpdef set_line(self, index_t line_nb, object value): - if obi_column_set_obiint_with_elt_idx(self.pointer, line_nb, 0, value) < 0: + if value is None : + value = OBIInt_NA + if obi_column_set_obiint_with_elt_idx_in_view(self.view, (self.pointer)[0], line_nb, 0, value) < 0: raise Exception("Problem setting a value in a column") - cpdef close(self): - if obi_truncate_and_close_column(self.pointer) < 0 : - raise Exception("Problem closing a column") - -cdef class OBIDMS_column_int_multi_elts(OBIDMS_column_int): +cdef class OBIDMS_column_multi_elts_int(OBIDMS_column_multi_elts): cpdef object get_item(self, index_t line_nb, str element_name): cdef obiint_t value cdef object result - value = obi_column_get_obiint_with_elt_name(self.pointer, line_nb, str2bytes(element_name)) + value = obi_column_get_obiint_with_elt_name_in_view(self.view, (self.pointer)[0], line_nb, str2bytes(element_name)) if obi_errno > 0 : raise IndexError(line_nb, element_name) if value == OBIInt_NA : @@ -63,42 +50,30 @@ cdef class OBIDMS_column_int_multi_elts(OBIDMS_column_int): cpdef object get_line(self, index_t line_nb) : cdef obiint_t value - cdef object result + cdef object value_in_result + cdef dict result cdef index_t i cdef bint all_NA result = {} all_NA = True for i in range(self.nb_elements_per_line) : - value = obi_column_get_obiint_with_elt_idx(self.pointer, line_nb, i) + value = obi_column_get_obiint_with_elt_idx_in_view(self.view, (self.pointer)[0], line_nb, i) if obi_errno > 0 : - raise IndexError(line_nb) - result[self.elements_names[i]] = PyInt_FromLong(value) - if all_NA and (value != OBIInt_NA) : + raise IndexError(line_nb) + if value == OBIInt_NA : + value_in_result = None + else : + value_in_result = PyInt_FromLong(value) + result[self.elements_names[i]] = value_in_result + if all_NA and (value_in_result is not None) : all_NA = False if all_NA : - result = None + result = None # TODO discuss return result - cpdef set_item(self, index_t line_nb, str element_name, obiint_t value): - raise Exception("Column is read-only") - - cpdef set_line(self, index_t line_nb, object values): - raise Exception("Column is read-only") - - -cdef class OBIDMS_column_int_multi_elts_writable(OBIDMS_column_int_multi_elts): - - cpdef set_item(self, index_t line_nb, str element_name, obiint_t value): - if obi_column_set_obiint_with_elt_name(self.pointer, line_nb, str2bytes(element_name), value) < 0: + cpdef set_item(self, index_t line_nb, str element_name, object value): + if value is None : + value = OBIInt_NA + if obi_column_set_obiint_with_elt_name_in_view(self.view, (self.pointer)[0], line_nb, str2bytes(element_name), value) < 0: raise Exception("Problem setting a value in a column") - - cpdef set_line(self, index_t line_nb, object values): - cdef obiint_t value - for element_name in values : - value = values[element_name] - self.set_item(line_nb, element_name, value) - - cpdef close(self): - if obi_truncate_and_close_column(self.pointer) < 0 : - raise Exception("Problem closing a column") diff --git a/python/obitools3/obidms/_obidmscolumn_seq.cfiles b/python/obitools3/obidms/_obidmscolumn_seq.cfiles index 857c9dc..379c552 100644 --- a/python/obitools3/obidms/_obidmscolumn_seq.cfiles +++ b/python/obitools3/obidms/_obidmscolumn_seq.cfiles @@ -1,5 +1,7 @@ ../../../src/obidmscolumn_seq.c ../../../src/obidmscolumn_seq.h +../../../src/obiview.h +../../../src/obiview.c ../../../src/obidmscolumn.h ../../../src/obidmscolumn.c ../../../src/obidmscolumndir.h diff --git a/python/obitools3/obidms/_obidmscolumn_seq.pxd b/python/obitools3/obidms/_obidmscolumn_seq.pxd index e06654e..bbece90 100644 --- a/python/obitools3/obidms/_obidmscolumn_seq.pxd +++ b/python/obitools3/obidms/_obidmscolumn_seq.pxd @@ -1,25 +1,14 @@ #cython: language_level=3 from .capi.obitypes cimport index_t -from ._obidms cimport OBIDMS_column +from ._obidms cimport OBIDMS_column, OBIDMS_column_multi_elts cdef class OBIDMS_column_seq(OBIDMS_column): cpdef object get_line(self, index_t line_nb) cpdef set_line(self, index_t line_nb, object value) - cpdef close(self) -cdef class OBIDMS_column_seq_writable(OBIDMS_column_seq): - cpdef set_line(self, index_t line_nb, object value) - cpdef close(self) - -cdef class OBIDMS_column_seq_multi_elts(OBIDMS_column_seq): +cdef class OBIDMS_column_multi_elts_seq(OBIDMS_column_multi_elts): cpdef object get_item(self, index_t line_nb, str element_name) cpdef object get_line(self, index_t line_nb) - cpdef set_item(self, index_t line_nb, str element_name, str value) - cpdef set_line(self, index_t line_nb, object values) - -cdef class OBIDMS_column_seq_multi_elts_writable(OBIDMS_column_seq_multi_elts): - cpdef set_item(self, index_t line_nb, str element_name, str value) - cpdef set_line(self, index_t line_nb, object values) - cpdef close(self) + cpdef set_item(self, index_t line_nb, str element_name, object value) diff --git a/python/obitools3/obidms/_obidmscolumn_seq.pyx b/python/obitools3/obidms/_obidmscolumn_seq.pyx index 4e71f35..7648719 100644 --- a/python/obitools3/obidms/_obidmscolumn_seq.pyx +++ b/python/obitools3/obidms/_obidmscolumn_seq.pyx @@ -1,13 +1,12 @@ #cython: language_level=3 -from .capi.obidmscolumn cimport obi_close_column,\ - obi_truncate_and_close_column, \ - obi_column_get_obiseq_with_elt_name, \ - obi_column_get_obiseq_with_elt_idx, \ - obi_column_set_obiseq_with_elt_name, \ - obi_column_set_obiseq_with_elt_idx +from .capi.obidmscolumn cimport obi_truncate_and_close_column, \ + obi_column_get_obiseq_with_elt_name_in_view, \ + obi_column_get_obiseq_with_elt_idx_in_view, \ + obi_column_set_obiseq_with_elt_name_in_view, \ + obi_column_set_obiseq_with_elt_idx_in_view from .capi.obierrno cimport obi_errno -from .capi.obitypes cimport OBIIdx_NA, const_char_p +from .capi.obitypes cimport OBISeq_NA, const_char_p from obitools3.utils cimport str2bytes, bytes2str @@ -17,87 +16,68 @@ cdef class OBIDMS_column_seq(OBIDMS_column): cpdef object get_line(self, index_t line_nb): cdef bytes value cdef object result - value = obi_column_get_obiseq_with_elt_idx(self.pointer, line_nb, 0) + value = obi_column_get_obiseq_with_elt_idx_in_view(self.view, (self.pointer)[0], line_nb, 0) if obi_errno > 0 : raise IndexError(line_nb) - if value == OBIIdx_NA : + if value == OBISeq_NA : # TODO result = None else : result = bytes2str(value) return result cpdef set_line(self, index_t line_nb, object value): - raise Exception("Column is read-only") - - cpdef close(self): - if obi_close_column(self.pointer) < 0 : - raise Exception("Problem closing a column") - - -cdef class OBIDMS_column_seq_writable(OBIDMS_column_seq): - - cpdef set_line(self, index_t line_nb, object value): - if obi_column_set_obiseq_with_elt_idx(self.pointer, line_nb, 0, str2bytes(value)) < 0: + cdef bytes value_b + if value is None : + value_b = OBISeq_NA + else : + value_b = str2bytes(value) + if obi_column_set_obiseq_with_elt_idx_in_view(self.view, (self.pointer)[0], line_nb, 0, value_b) < 0: raise Exception("Problem setting a value in a column") - cpdef close(self): - if obi_truncate_and_close_column(self.pointer) < 0 : - raise Exception("Problem closing a column") - -cdef class OBIDMS_column_seq_multi_elts(OBIDMS_column_seq): +cdef class OBIDMS_column_multi_elts_seq(OBIDMS_column_multi_elts): cpdef object get_item(self, index_t line_nb, str element_name): cdef bytes value cdef object result - value = obi_column_get_obiseq_with_elt_name(self.pointer, line_nb, str2bytes(element_name)) + value = obi_column_get_obiseq_with_elt_name_in_view(self.view, (self.pointer)[0], line_nb, str2bytes(element_name)) if obi_errno > 0 : raise IndexError(line_nb, element_name) - if value == OBIIdx_NA : + if value == OBISeq_NA : result = None else : result = bytes2str(value) return result - + cpdef object get_line(self, index_t line_nb) : cdef bytes value - cdef object result + cdef object value_in_result + cdef dict result cdef index_t i cdef bint all_NA result = {} all_NA = True for i in range(self.nb_elements_per_line) : - value = obi_column_get_obiseq_with_elt_idx(self.pointer, line_nb, i) + value = obi_column_get_obiseq_with_elt_idx_in_view(self.view, (self.pointer)[0], line_nb, i) if obi_errno > 0 : - raise IndexError(line_nb) - result[self.elements_names[i]] = bytes2str(value) - if all_NA and (value != OBIIdx_NA) : + raise IndexError(line_nb) + if value == OBISeq_NA : + value_in_result = None + else : + value_in_result = bytes2str(value) + result[self.elements_names[i]] = value_in_result + if all_NA and (value_in_result is not None) : all_NA = False if all_NA : result = None return result - cpdef set_item(self, index_t line_nb, str element_name, str value): - raise Exception("Column is read-only") - - cpdef set_line(self, index_t line_nb, object values): - raise Exception("Column is read-only") - - -cdef class OBIDMS_column_seq_multi_elts_writable(OBIDMS_column_seq_multi_elts): - - cpdef set_item(self, index_t line_nb, str element_name, str value): - if obi_column_set_obiseq_with_elt_name(self.pointer, line_nb, str2bytes(element_name), str2bytes(value)) < 0: + cpdef set_item(self, index_t line_nb, str element_name, object value): + cdef bytes value_b + if value is None : + value_b = OBISeq_NA + else : + value_b = str2bytes(value) + if obi_column_set_obiseq_with_elt_name_in_view(self.view, (self.pointer)[0], line_nb, str2bytes(element_name), value_b) < 0: raise Exception("Problem setting a value in a column") - cpdef set_line(self, index_t line_nb, object values): - cdef str value - for element_name in values : - value = values[element_name] - self.set_item(line_nb, element_name, value) - - cpdef close(self): - if obi_truncate_and_close_column(self.pointer) < 0 : - raise Exception("Problem closing a column") - - \ No newline at end of file diff --git a/python/obitools3/obidms/_obidmscolumn_str.cfiles b/python/obitools3/obidms/_obidmscolumn_str.cfiles index 9f7af7b..006aa64 100644 --- a/python/obitools3/obidms/_obidmscolumn_str.cfiles +++ b/python/obitools3/obidms/_obidmscolumn_str.cfiles @@ -1,5 +1,7 @@ ../../../src/obidmscolumn_str.c ../../../src/obidmscolumn_str.h +../../../src/obiview.h +../../../src/obiview.c ../../../src/obidmscolumn.h ../../../src/obidmscolumn.c ../../../src/obidmscolumndir.h diff --git a/python/obitools3/obidms/_obidmscolumn_str.pxd b/python/obitools3/obidms/_obidmscolumn_str.pxd index 62fc0e3..7c813d0 100644 --- a/python/obitools3/obidms/_obidmscolumn_str.pxd +++ b/python/obitools3/obidms/_obidmscolumn_str.pxd @@ -1,25 +1,14 @@ #cython: language_level=3 from .capi.obitypes cimport index_t -from ._obidms cimport OBIDMS_column +from ._obidms cimport OBIDMS_column, OBIDMS_column_multi_elts cdef class OBIDMS_column_str(OBIDMS_column): cpdef object get_line(self, index_t line_nb) cpdef set_line(self, index_t line_nb, object value) - cpdef close(self) -cdef class OBIDMS_column_str_writable(OBIDMS_column_str): - cpdef set_line(self, index_t line_nb, object value) - cpdef close(self) - -cdef class OBIDMS_column_str_multi_elts(OBIDMS_column_str): +cdef class OBIDMS_column_multi_elts_str(OBIDMS_column_multi_elts): cpdef object get_item(self, index_t line_nb, str element_name) cpdef object get_line(self, index_t line_nb) - cpdef set_item(self, index_t line_nb, str element_name, str value) - cpdef set_line(self, index_t line_nb, object values) - -cdef class OBIDMS_column_str_multi_elts_writable(OBIDMS_column_str_multi_elts): - cpdef set_item(self, index_t line_nb, str element_name, str value) - cpdef set_line(self, index_t line_nb, object values) - cpdef close(self) + cpdef set_item(self, index_t line_nb, str element_name, object value) diff --git a/python/obitools3/obidms/_obidmscolumn_str.pyx b/python/obitools3/obidms/_obidmscolumn_str.pyx index 433b5d5..0041872 100644 --- a/python/obitools3/obidms/_obidmscolumn_str.pyx +++ b/python/obitools3/obidms/_obidmscolumn_str.pyx @@ -1,13 +1,12 @@ #cython: language_level=3 -from .capi.obidmscolumn cimport obi_close_column,\ - obi_truncate_and_close_column, \ - obi_column_get_obistr_with_elt_name, \ - obi_column_get_obistr_with_elt_idx, \ - obi_column_set_obistr_with_elt_name, \ - obi_column_set_obistr_with_elt_idx +from .capi.obidmscolumn cimport obi_truncate_and_close_column, \ + obi_column_get_obistr_with_elt_name_in_view, \ + obi_column_get_obistr_with_elt_idx_in_view, \ + obi_column_set_obistr_with_elt_name_in_view, \ + obi_column_set_obistr_with_elt_idx_in_view from .capi.obierrno cimport obi_errno -from .capi.obitypes cimport OBIIdx_NA, const_char_p +from .capi.obitypes cimport OBIStr_NA, const_char_p from obitools3.utils cimport str2bytes, bytes2str @@ -17,87 +16,68 @@ cdef class OBIDMS_column_str(OBIDMS_column): cpdef object get_line(self, index_t line_nb): cdef bytes value cdef object result - value = obi_column_get_obistr_with_elt_idx(self.pointer, line_nb, 0) + value = obi_column_get_obistr_with_elt_idx_in_view(self.view, (self.pointer)[0], line_nb, 0) if obi_errno > 0 : raise IndexError(line_nb) - if value == OBIIdx_NA : + if value == OBIStr_NA : # TODO result = None else : result = bytes2str(value) return result cpdef set_line(self, index_t line_nb, object value): - raise Exception("Column is read-only") - - cpdef close(self): - if obi_close_column(self.pointer) < 0 : - raise Exception("Problem closing a column") - - -cdef class OBIDMS_column_str_writable(OBIDMS_column_str): - - cpdef set_line(self, index_t line_nb, object value): - if obi_column_set_obistr_with_elt_idx(self.pointer, line_nb, 0, str2bytes(value)) < 0: + cdef bytes value_b + if value is None : + value_b = OBIStr_NA + else : + value_b = str2bytes(value) + if obi_column_set_obistr_with_elt_idx_in_view(self.view, (self.pointer)[0], line_nb, 0, value_b) < 0: raise Exception("Problem setting a value in a column") - cpdef close(self): - if obi_truncate_and_close_column(self.pointer) < 0 : - raise Exception("Problem closing a column") - -cdef class OBIDMS_column_str_multi_elts(OBIDMS_column_str): +cdef class OBIDMS_column_multi_elts_str(OBIDMS_column_multi_elts): cpdef object get_item(self, index_t line_nb, str element_name): cdef bytes value cdef object result - value = obi_column_get_obistr_with_elt_name(self.pointer, line_nb, str2bytes(element_name)) + value = obi_column_get_obistr_with_elt_name_in_view(self.view, (self.pointer)[0], line_nb, str2bytes(element_name)) if obi_errno > 0 : raise IndexError(line_nb, element_name) - if value == OBIIdx_NA : + if value == OBIStr_NA : result = None else : result = bytes2str(value) return result - + cpdef object get_line(self, index_t line_nb) : cdef bytes value - cdef object result + cdef object value_in_result + cdef dict result cdef index_t i cdef bint all_NA result = {} all_NA = True for i in range(self.nb_elements_per_line) : - value = obi_column_get_obistr_with_elt_idx(self.pointer, line_nb, i) + value = obi_column_get_obistr_with_elt_idx_in_view(self.view, (self.pointer)[0], line_nb, i) if obi_errno > 0 : - raise IndexError(line_nb) - result[self.elements_names[i]] = bytes2str(value) - if all_NA and (value != OBIIdx_NA) : + raise IndexError(line_nb) + if value == OBIStr_NA : + value_in_result = None + else : + value_in_result = bytes2str(value) + result[self.elements_names[i]] = value_in_result + if all_NA and (value_in_result is not None) : all_NA = False if all_NA : result = None return result - cpdef set_item(self, index_t line_nb, str element_name, str value): - raise Exception("Column is read-only") - - cpdef set_line(self, index_t line_nb, object values): - raise Exception("Column is read-only") - - -cdef class OBIDMS_column_str_multi_elts_writable(OBIDMS_column_str_multi_elts): - - cpdef set_item(self, index_t line_nb, str element_name, str value): - if obi_column_set_obistr_with_elt_name(self.pointer, line_nb, str2bytes(element_name), str2bytes(value)) < 0: + cpdef set_item(self, index_t line_nb, str element_name, object value): + cdef bytes value_b + if value is None : + value_b = OBIStr_NA + else : + value_b = str2bytes(value) + if obi_column_set_obistr_with_elt_name_in_view(self.view, (self.pointer)[0], line_nb, str2bytes(element_name), value_b) < 0: raise Exception("Problem setting a value in a column") - cpdef set_line(self, index_t line_nb, object values): - cdef str value - for element_name in values : - value = values[element_name] - self.set_item(line_nb, element_name, value) - - cpdef close(self): - if obi_truncate_and_close_column(self.pointer) < 0 : - raise Exception("Problem closing a column") - - \ No newline at end of file diff --git a/python/obitools3/obidms/capi/obidmscolumn.pxd b/python/obitools3/obidms/capi/obidmscolumn.pxd index d3bae82..90ea869 100644 --- a/python/obitools3/obidms/capi/obidmscolumn.pxd +++ b/python/obitools3/obidms/capi/obidmscolumn.pxd @@ -19,16 +19,13 @@ cdef extern from "obidmscolumn.h" nogil: size_t data_size index_t line_count index_t lines_used - index_t returned_nb_elements_per_line - index_t stored_nb_elements_per_line + index_t nb_elements_per_line const_char_p elements_names OBIType_t returned_data_type OBIType_t stored_data_type time_t creation_date obiversion_t version obiversion_t cloned_from - bint referring - obiversion_t referred_column_version const_char_p name const_char_p avl_name const_char_p comments @@ -36,9 +33,10 @@ cdef extern from "obidmscolumn.h" nogil: ctypedef OBIDMS_column_header_t* OBIDMS_column_header_p struct OBIDMS_column_t: + OBIDMS_p dms OBIDMS_column_header_p header - OBIDMS_column_t* referred_column - + bint writable + ctypedef OBIDMS_column_t* OBIDMS_column_p OBIDMS_column_p obi_create_column(OBIDMS_p dms, @@ -48,8 +46,7 @@ cdef extern from "obidmscolumn.h" nogil: index_t nb_elements_per_line, const_char_p elements_names, const_char_p avl_name, - const_char_p comments, - bint referring) + const_char_p comments) OBIDMS_column_p obi_open_column(OBIDMS_p dms, const_char_p column_name, @@ -58,9 +55,9 @@ cdef extern from "obidmscolumn.h" nogil: int obi_close_column(OBIDMS_column_p column) OBIDMS_column_p obi_clone_column(OBIDMS_p dms, + OBIDMS_column_p line_selection, const_char_p column_name, obiversion_t version_number, - bint referring, bint clone_data) int obi_truncate_and_close_column(OBIDMS_column_p column) @@ -76,10 +73,34 @@ cdef extern from "obidmscolumn.h" nogil: char* obi_column_format_date(time_t date) - int obi_grep_line(OBIDMS_column_p referring_column, index_t line_to_grep) + int obi_select(OBIDMS_column_p line_selection_column, index_t line_to_grep) + + +from ..capi.obiview cimport Obiview_p # TODO - cdef extern from "obidmscolumn_int.h" nogil: + int obi_column_set_obiint_with_elt_name_in_view(Obiview_p view, + OBIDMS_column_p column, + index_t line_nb, + const_char_p element_name, + obiint_t value) + + int obi_column_set_obiint_with_elt_idx_in_view(Obiview_p view, + OBIDMS_column_p column, + index_t line_nb, + index_t element_idx, + obiint_t value) + + obiint_t obi_column_get_obiint_with_elt_name_in_view(Obiview_p view, + OBIDMS_column_p column, + index_t line_nb, + const_char_p element_name) + + obiint_t obi_column_get_obiint_with_elt_idx_in_view(Obiview_p view, + OBIDMS_column_p column, + index_t line_nb, + index_t element_idx) + int obi_column_set_obiint_with_elt_name(OBIDMS_column_p column, index_t line_nb, const_char_p element_name, @@ -88,7 +109,7 @@ cdef extern from "obidmscolumn_int.h" nogil: int obi_column_set_obiint_with_elt_idx(OBIDMS_column_p column, index_t line_nb, index_t element_idx, - obiint_t value) + obiint_t value) obiint_t obi_column_get_obiint_with_elt_name(OBIDMS_column_p column, index_t line_nb, @@ -98,14 +119,35 @@ cdef extern from "obidmscolumn_int.h" nogil: index_t line_nb, index_t element_idx) - cdef extern from "obidmscolumn_bool.h" nogil: + int obi_column_set_obibool_with_elt_name_in_view(Obiview_p view, + OBIDMS_column_p column, + index_t line_nb, + const_char_p element_name, + obibool_t value) + + int obi_column_set_obibool_with_elt_idx_in_view(Obiview_p view, + OBIDMS_column_p column, + index_t line_nb, + index_t element_idx, + obibool_t value) + + obibool_t obi_column_get_obibool_with_elt_name_in_view(Obiview_p view, + OBIDMS_column_p column, + index_t line_nb, + const_char_p element_name) + + obibool_t obi_column_get_obibool_with_elt_idx_in_view(Obiview_p view, + OBIDMS_column_p column, + index_t line_nb, + index_t element_idx) + int obi_column_set_obibool_with_elt_name(OBIDMS_column_p column, index_t line_nb, const_char_p element_name, obibool_t value) - + int obi_column_set_obibool_with_elt_idx(OBIDMS_column_p column, index_t line_nb, index_t element_idx, @@ -121,11 +163,33 @@ cdef extern from "obidmscolumn_bool.h" nogil: cdef extern from "obidmscolumn_char.h" nogil: + int obi_column_set_obichar_with_elt_name_in_view(Obiview_p view, + OBIDMS_column_p column, + index_t line_nb, + const_char_p element_name, + obichar_t value) + + int obi_column_set_obichar_with_elt_idx_in_view(Obiview_p view, + OBIDMS_column_p column, + index_t line_nb, + index_t element_idx, + obichar_t value) + + obichar_t obi_column_get_obichar_with_elt_name_in_view(Obiview_p view, + OBIDMS_column_p column, + index_t line_nb, + const_char_p element_name) + + obichar_t obi_column_get_obichar_with_elt_idx_in_view(Obiview_p view, + OBIDMS_column_p column, + index_t line_nb, + index_t element_idx) + int obi_column_set_obichar_with_elt_name(OBIDMS_column_p column, index_t line_nb, const_char_p element_name, obichar_t value) - + int obi_column_set_obichar_with_elt_idx(OBIDMS_column_p column, index_t line_nb, index_t element_idx, @@ -141,39 +205,83 @@ cdef extern from "obidmscolumn_char.h" nogil: cdef extern from "obidmscolumn_float.h" nogil: - int obi_column_set_obifloat_with_elt_name(OBIDMS_column_p column, - index_t line_nb, - const_char_p element_name, - obifloat_t value) + int obi_column_set_obifloat_with_elt_name_in_view(Obiview_p view, + OBIDMS_column_p column, + index_t line_nb, + const_char_p element_name, + obifloat_t value) + + int obi_column_set_obifloat_with_elt_idx_in_view(Obiview_p view, + OBIDMS_column_p column, + index_t line_nb, + index_t element_idx, + obifloat_t value) - int obi_column_set_obifloat_with_elt_idx(OBIDMS_column_p column, + obifloat_t obi_column_get_obifloat_with_elt_name_in_view(Obiview_p view, + OBIDMS_column_p column, + index_t line_nb, + const_char_p element_name) + + obifloat_t obi_column_get_obifloat_with_elt_idx_in_view(Obiview_p view, + OBIDMS_column_p column, + index_t line_nb, + index_t element_idx) + + int obi_column_set_obifloat_with_elt_name(OBIDMS_column_p column, index_t line_nb, - index_t element_idx, + const_char_p element_name, obifloat_t value) + + int obi_column_set_obifloat_with_elt_idx(OBIDMS_column_p column, + index_t line_nb, + index_t element_idx, + obifloat_t value) obifloat_t obi_column_get_obifloat_with_elt_name(OBIDMS_column_p column, - index_t line_nb, - const_char_p element_name) + index_t line_nb, + const_char_p element_name) obifloat_t obi_column_get_obifloat_with_elt_idx(OBIDMS_column_p column, - index_t line_nb, - index_t element_idx) + index_t line_nb, + index_t element_idx) cdef extern from "obidmscolumn_str.h" nogil: + int obi_column_set_obistr_with_elt_name_in_view(Obiview_p view, + OBIDMS_column_p column, + index_t line_nb, + const_char_p element_name, + char* value) + + int obi_column_set_obistr_with_elt_idx_in_view(Obiview_p view, + OBIDMS_column_p column, + index_t line_nb, + index_t element_idx, + char* value) + + const_char_p obi_column_get_obistr_with_elt_name_in_view(Obiview_p view, + OBIDMS_column_p column, + index_t line_nb, + const_char_p element_name) + + const_char_p obi_column_get_obistr_with_elt_idx_in_view(Obiview_p view, + OBIDMS_column_p column, + index_t line_nb, + index_t element_idx) + int obi_column_set_obistr_with_elt_name(OBIDMS_column_p column, index_t line_nb, const_char_p element_name, char* value) - + int obi_column_set_obistr_with_elt_idx(OBIDMS_column_p column, index_t line_nb, index_t element_idx, char* value) const_char_p obi_column_get_obistr_with_elt_name(OBIDMS_column_p column, - index_t line_nb, - const_char_p element_name) + index_t line_nb, + char* element_name) const_char_p obi_column_get_obistr_with_elt_idx(OBIDMS_column_p column, index_t line_nb, @@ -181,19 +289,41 @@ cdef extern from "obidmscolumn_str.h" nogil: cdef extern from "obidmscolumn_seq.h" nogil: + int obi_column_set_obiseq_with_elt_name_in_view(Obiview_p view, + OBIDMS_column_p column, + index_t line_nb, + const_char_p element_name, + char* value) + + int obi_column_set_obiseq_with_elt_idx_in_view(Obiview_p view, + OBIDMS_column_p column, + index_t line_nb, + index_t element_idx, + char* value) + + const_char_p obi_column_get_obiseq_with_elt_name_in_view(Obiview_p view, + OBIDMS_column_p column, + index_t line_nb, + const_char_p element_name) + + const_char_p obi_column_get_obiseq_with_elt_idx_in_view(Obiview_p view, + OBIDMS_column_p column, + index_t line_nb, + index_t element_idx) + int obi_column_set_obiseq_with_elt_name(OBIDMS_column_p column, index_t line_nb, const_char_p element_name, char* value) - + int obi_column_set_obiseq_with_elt_idx(OBIDMS_column_p column, index_t line_nb, index_t element_idx, char* value) const_char_p obi_column_get_obiseq_with_elt_name(OBIDMS_column_p column, - index_t line_nb, - const_char_p element_name) + index_t line_nb, + char* element_name) const_char_p obi_column_get_obiseq_with_elt_idx(OBIDMS_column_p column, index_t line_nb, diff --git a/python/obitools3/obidms/capi/obitypes.pxd b/python/obitools3/obidms/capi/obitypes.pxd index 22abea1..57d3461 100644 --- a/python/obitools3/obidms/capi/obitypes.pxd +++ b/python/obitools3/obidms/capi/obitypes.pxd @@ -8,6 +8,9 @@ from posix.types cimport time_t cdef extern from *: ctypedef char* const_char_p "const char*" +cdef extern from "encode.h" nogil: + bint only_ATGC(const_char_p seq) + cdef extern from "obidmscolumn.h" nogil: @@ -38,10 +41,12 @@ cdef extern from "obitypes.h" nogil: ctypedef char obichar_t ctypedef int64_t index_t - extern obiint_t OBIInt_NA - extern index_t OBIIdx_NA - extern obifloat_t OBIFloat_NA - extern obichar_t OBIChar_NA - extern obibool_t OBIBool_NA + extern obiint_t OBIInt_NA + extern index_t OBIIdx_NA + extern obifloat_t OBIFloat_NA + extern obichar_t OBIChar_NA + extern obibool_t OBIBool_NA + extern const_char_p OBISeq_NA + extern const_char_p OBIStr_NA - char* name_data_type(int data_type) + const_char_p name_data_type(int data_type) diff --git a/python/obitools3/obidms/capi/obiview.pxd b/python/obitools3/obidms/capi/obiview.pxd new file mode 100644 index 0000000..b5df3b6 --- /dev/null +++ b/python/obitools3/obidms/capi/obiview.pxd @@ -0,0 +1,68 @@ +#cython: language_level=3 + +from .obitypes cimport const_char_p, \ + OBIType_t, \ + obiversion_t, \ + index_t +from ..capi.obidms cimport OBIDMS_p +from ..capi.obidmscolumn cimport OBIDMS_column_p + + +cdef extern from "obiview.h" nogil: + + struct Column_reference_t : + char column_name + obiversion_t version + + ctypedef Column_reference_t* Column_reference_p + + + struct Obiview_t : + OBIDMS_p dms + const_char_p name + OBIDMS_column_p line_selection + OBIDMS_column_p new_line_selection + OBIDMS_column_p columns + bint read_only + Column_reference_t line_selection_reference + index_t line_count + int column_count + + ctypedef Obiview_t* Obiview_p + + + Obiview_p obi_new_view(OBIDMS_p dms, const_char_p view_name, Obiview_p view_to_clone, index_t* line_selection) + + Obiview_p obi_new_view_cloned_from_name(OBIDMS_p dms, const char* view_name, const char* view_to_clone_name, index_t* line_selection) + + Obiview_p obi_open_view(OBIDMS_p dms, const_char_p view_name) + + int obi_view_add_column(Obiview_p view, + const_char_p column_name, + obiversion_t version_number, + OBIType_t data_type, + index_t nb_lines, + index_t nb_elements_per_line, + const_char_p elements_names, + const_char_p avl_name, + const_char_p comments, + bint create) + + int obi_view_delete_column(Obiview_p view, const_char_p column_name) + + int obi_select_line(Obiview_p view, index_t line_nb) + + int obi_select_lines(Obiview_p view, index_t* line_nbs) + + OBIDMS_column_p obi_view_clone_column(Obiview_p view, const_char_p column_name) + + OBIDMS_column_p obi_view_get_column(Obiview_p view, const_char_p column_name) + + OBIDMS_column_p* obi_view_get_pointer_on_column_in_view(Obiview_p view, const_char_p column_name) + + int obi_save_view(Obiview_p view) + + int obi_close_view(Obiview_p view) + + int obi_save_and_close_view(Obiview_p view) + diff --git a/src/obidms.c b/src/obidms.c index d2cb509..68a27c3 100644 --- a/src/obidms.c +++ b/src/obidms.c @@ -202,8 +202,8 @@ int create_dms_infos_file(int dms_file_descriptor, const char* dms_name) int obi_dms_exists(const char* dms_name) { struct stat buffer; - char *directory_name; - int check_dir; + char* directory_name; + int check_dir; // Build and check the directory name directory_name = build_directory_name(dms_name); diff --git a/src/obidms.h b/src/obidms.h index 6f94b0e..b1e0804 100644 --- a/src/obidms.h +++ b/src/obidms.h @@ -39,7 +39,7 @@ struct OBIDMS_column; // TODO typedef struct Opened_columns_list { size_t nb_opened_columns; - struct OBIDMS_column** columns; + struct OBIDMS_column** columns; // TODO allocate array size here } Opened_columns_list_t, *Opened_columns_list_p; diff --git a/src/obidmscolumn.c b/src/obidmscolumn.c index 01898d4..4f5f4bc 100644 --- a/src/obidmscolumn.c +++ b/src/obidmscolumn.c @@ -515,8 +515,8 @@ OBIDMS_column_p obi_create_column(OBIDMS_p dms, index_t nb_elements_per_line, const char* elements_names, const char* avl_name, - const char* comments, - bool referring) + const char* comments + ) { OBIDMS_column_p new_column; OBIDMS_column_directory_p column_directory; @@ -531,8 +531,6 @@ OBIDMS_column_p obi_create_column(OBIDMS_p dms, index_t minimum_line_count; OBIType_t returned_data_type; OBIType_t stored_data_type; - index_t returned_nb_elements_per_line; - index_t stored_nb_elements_per_line; new_column = NULL; @@ -547,7 +545,7 @@ OBIDMS_column_p obi_create_column(OBIDMS_p dms, obidebug(1, "\nCan't create column because of empty column name"); return NULL; } - if ((data_type < 1) || (data_type > 6)) + if ((data_type < 1) || (data_type > 7)) { obidebug(1, "\nCan't create column because of invalid data type"); return NULL; @@ -559,21 +557,14 @@ OBIDMS_column_p obi_create_column(OBIDMS_p dms, } returned_data_type = data_type; - if ((data_type == OBI_STR) || (data_type == OBI_SEQ) || referring) + if ((data_type == OBI_STR) || (data_type == OBI_SEQ)) // stored data is indices referring to data stored elsewhere stored_data_type = OBI_IDX; else stored_data_type = returned_data_type; - returned_nb_elements_per_line = nb_elements_per_line; - if (referring) - // stored data is indices referring to lines in another column - stored_nb_elements_per_line = 1; - else - stored_nb_elements_per_line = returned_nb_elements_per_line; - // The initial line count should be between the minimum (corresponding to the page size) and the maximum allowed - minimum_line_count = get_line_count_per_page(stored_data_type, stored_nb_elements_per_line); + minimum_line_count = get_line_count_per_page(stored_data_type, nb_elements_per_line); if (nb_lines > MAXIMUM_LINE_COUNT) { obidebug(1, "\nCan't create column because of line count greater than the maximum allowed (%d)", MAXIMUM_LINE_COUNT); @@ -583,12 +574,12 @@ OBIDMS_column_p obi_create_column(OBIDMS_p dms, nb_lines = minimum_line_count; // The number of elements names should be equal to the number of elements per line - if ((elements_names == NULL) && (returned_nb_elements_per_line > 1)) + if ((elements_names == NULL) && (nb_elements_per_line > 1)) { obidebug(1, "\nCan't create column because no elements names were given for a number of elements per line greater than 1"); return NULL; } - else if ((elements_names != NULL) && (returned_nb_elements_per_line > 1)) + else if ((elements_names != NULL) && (nb_elements_per_line > 1)) { char* token; index_t n = 0; @@ -605,7 +596,7 @@ OBIDMS_column_p obi_create_column(OBIDMS_p dms, return NULL; } } - else if ((returned_nb_elements_per_line == 1) && (strcmp(elements_names, column_name) != 0)) + else if ((nb_elements_per_line == 1) && (strcmp(elements_names, column_name) != 0)) { obidebug(1, "\nCan't create column because the element name does not match the column name"); return NULL; @@ -622,7 +613,7 @@ OBIDMS_column_p obi_create_column(OBIDMS_p dms, // Calculate the size needed header_size = obi_get_platform_header_size(); - data_size = obi_array_sizeof(stored_data_type, nb_lines, stored_nb_elements_per_line); + data_size = obi_array_sizeof(stored_data_type, nb_lines, nb_elements_per_line); file_size = header_size + data_size; // Get the latest version number @@ -708,22 +699,19 @@ OBIDMS_column_p obi_create_column(OBIDMS_p dms, return NULL; } - new_column->writable = true; + new_column->writable = true; header = new_column->header; header->header_size = header_size; header->data_size = data_size; header->line_count = nb_lines; header->lines_used = 0; - header->stored_nb_elements_per_line = stored_nb_elements_per_line; - header->returned_nb_elements_per_line = returned_nb_elements_per_line; + header->nb_elements_per_line = nb_elements_per_line; header->stored_data_type = stored_data_type; header->returned_data_type = returned_data_type; header->creation_date = time(NULL); header->version = version_number; header->cloned_from = -1; - header->referring = referring; - header->referred_column_version = -1; obi_column_set_elements_names(new_column, elements_names); @@ -780,7 +768,7 @@ OBIDMS_column_p obi_open_column(OBIDMS_p dms, column_directory = obi_open_column_directory(dms, column_name); if (column_directory == NULL) { - obidebug(1, "\nError opening a column directory structure"); + //obidebug(1, "\nError opening a column directory structure"); return NULL; } @@ -818,7 +806,7 @@ OBIDMS_column_p obi_open_column(OBIDMS_p dms, if (column_file_descriptor < 0) { obi_set_errno(OBICOL_UNKNOWN_ERROR); - obidebug(1, "\nError opening column file"); + //obidebug(1, "\nError opening column file"); free(column_file_name); return NULL; } @@ -854,7 +842,7 @@ OBIDMS_column_p obi_open_column(OBIDMS_p dms, MAP_PRIVATE, column_file_descriptor, 0 - ); + ); if (column->header == MAP_FAILED) { @@ -872,7 +860,7 @@ OBIDMS_column_p obi_open_column(OBIDMS_p dms, MAP_PRIVATE, column_file_descriptor, header_size - ); + ); if (column->data == MAP_FAILED) { @@ -884,7 +872,7 @@ OBIDMS_column_p obi_open_column(OBIDMS_p dms, return NULL; } - column->writable = false; + column->writable = false; // If the data type is OBI_STR or OBI_SEQ, the associated AVL tree is opened if (((column->header)->returned_data_type == OBI_STR) || ((column->header)->returned_data_type == OBI_SEQ)) @@ -901,18 +889,6 @@ OBIDMS_column_p obi_open_column(OBIDMS_p dms, column->avl = avl; } - if ((column->header)->referring) - { - column->referred_column = obi_open_column(dms, column_name, (column->header)->referred_column_version); - if (column->referred_column == NULL) - { - obidebug(1, "\nError opening a referred column"); - obi_close_column(column); - close(column_file_descriptor); - return NULL; - } - } - close(column_file_descriptor); // Add in the list of opened columns and set column counter to 1 @@ -925,9 +901,9 @@ OBIDMS_column_p obi_open_column(OBIDMS_p dms, OBIDMS_column_p obi_clone_column(OBIDMS_p dms, + OBIDMS_column_p line_selection, const char* column_name, obiversion_t version_number, - bool referring, bool clone_data) { OBIDMS_column_p column_to_clone; @@ -935,6 +911,10 @@ OBIDMS_column_p obi_clone_column(OBIDMS_p dms, index_t nb_lines; index_t nb_elements_per_line; OBIType_t data_type; + size_t line_size; + index_t i, index; + + obidebug(1, "\nline_selection == NULL = %d\n", (line_selection == NULL)); column_to_clone = obi_open_column(dms, column_name, version_number); if (column_to_clone == NULL) @@ -944,25 +924,11 @@ OBIDMS_column_p obi_clone_column(OBIDMS_p dms, return NULL; } - // A referring column can't be cloned - if ((column_to_clone->header)->referring) - { - obi_set_errno(OBICOL_UNKNOWN_ERROR); - obidebug(1, "\nError: can't clone a referring column"); - return NULL; - } - data_type = (column_to_clone->header)->returned_data_type; - nb_elements_per_line = (column_to_clone->header)->returned_nb_elements_per_line; + nb_elements_per_line = (column_to_clone->header)->nb_elements_per_line; - if (clone_data && referring) - { - obi_set_errno(OBICOL_UNKNOWN_ERROR); - obidebug(1, "\nError: can't clone the data when creating a referring column"); - return NULL; - } - else if (clone_data) + if (clone_data) nb_lines = (column_to_clone->header)->line_count; else nb_lines = get_line_count_per_page(data_type, nb_elements_per_line); // minimum line count corresponding to one memory page @@ -974,8 +940,8 @@ OBIDMS_column_p obi_clone_column(OBIDMS_p dms, nb_elements_per_line, (column_to_clone->header)->elements_names, (column_to_clone->header)->avl_name, - (column_to_clone->header)->comments, - referring); + (column_to_clone->header)->comments + ); if (new_column == NULL) { @@ -989,24 +955,29 @@ OBIDMS_column_p obi_clone_column(OBIDMS_p dms, (new_column->header)->cloned_from = (column_to_clone->header)->version; - if (referring) - { - if ((column_to_clone->header)->referring) - (new_column->header)->referred_column_version = (column_to_clone->header)->referred_column_version; - else - (new_column->header)->referred_column_version = (column_to_clone->header)->version; - } - - if (clone_data) + if (clone_data && (line_selection == NULL)) { memcpy(new_column->data, column_to_clone->data, (column_to_clone->header)->data_size); (new_column->header)->lines_used = (column_to_clone->header)->lines_used; } + else if (clone_data && (line_selection != NULL)) + { + obidebug(1, "\nCloning data from line selection\n"); + line_size = obi_sizeof((new_column->header)->stored_data_type) * (new_column->header)->nb_elements_per_line; + fprintf(stderr, "\nline size = %ld\n", line_size); + for (i=0; i<((line_selection->header)->lines_used); i++) + { + index = *(((index_t*) (line_selection->data)) + i); + fprintf(stderr, "\nindex = %lld, i = %lld\n", index, i); + memcpy((new_column->data)+(i*line_size), (column_to_clone->data)+(index*line_size), line_size); + fprintf(stderr, "\nmemcpied\n"); + } + (new_column->header)->lines_used = (line_selection->header)->lines_used; + obidebug(1, "\nCloned data from line selection\n"); + } - // close column_to_clone or store the pointer if it's referred - if (referring) - new_column->referred_column = column_to_clone; - else if (obi_close_column(column_to_clone) < 0) + // Close column_to_clone + if (obi_close_column(column_to_clone) < 0) { obidebug(1, "\nError closing a column that has been cloned"); // TODO return NULL or not? @@ -1049,9 +1020,6 @@ int obi_close_column(OBIDMS_column_p column) } } - if ((column->header)->referring) - obi_close_column(column->referred_column); - // If the data type is OBI_STR or OBI_SEQ, the associated AVL tree is closed if (((column->header)->returned_data_type == OBI_STR) || ((column->header)->returned_data_type == OBI_SEQ)) { @@ -1095,8 +1063,8 @@ int obi_truncate_column_to_lines_used(OBIDMS_column_p column) // TODO is it nece char* column_file_name; // Compute the new line count = the number of lines used rounded to the nearest greater multiple of page size greater than 0 - multiple = ceil((double) (ONE_IF_ZERO((column->header)->lines_used) * (column->header)->stored_nb_elements_per_line * obi_sizeof((column->header)->stored_data_type)) / (double) getpagesize()); - new_line_count = floor((((int) multiple) * getpagesize()) / ((column->header)->stored_nb_elements_per_line * obi_sizeof((column->header)->stored_data_type))); + multiple = ceil((double) (ONE_IF_ZERO((column->header)->lines_used) * (column->header)->nb_elements_per_line * obi_sizeof((column->header)->stored_data_type)) / (double) getpagesize()); + new_line_count = floor((((int) multiple) * getpagesize()) / ((column->header)->nb_elements_per_line * obi_sizeof((column->header)->stored_data_type))); // Check that it is actually greater than the current number of lines allocated in the file, otherwise no need to truncate if ((column->header)->line_count == new_line_count) @@ -1131,7 +1099,7 @@ int obi_truncate_column_to_lines_used(OBIDMS_column_p column) // TODO is it nece } // Truncate the column file - data_size = obi_array_sizeof((column->header)->stored_data_type, new_line_count, (column->header)->stored_nb_elements_per_line); + data_size = obi_array_sizeof((column->header)->stored_data_type, new_line_count, (column->header)->nb_elements_per_line); file_size = (column->header)->header_size + data_size; if (ftruncate(column_file_descriptor, file_size) < 0) { @@ -1262,8 +1230,11 @@ int obi_enlarge_column(OBIDMS_column_p column) int obi_truncate_and_close_column(OBIDMS_column_p column) { - if (obi_truncate_column_to_lines_used(column) < 0) - return -1; + if (column->writable) // TODO discuss + { + if (obi_truncate_column_to_lines_used(column) < 0) + return -1; + } if (obi_close_column(column) < 0) return -1; @@ -1277,8 +1248,8 @@ void obi_ini_to_NA_values(OBIDMS_column_p column, { index_t i, start, end, nb_elements; - nb_elements = nb_lines*((column->header)->stored_nb_elements_per_line); - start = first_line_nb*((column->header)->stored_nb_elements_per_line); + nb_elements = nb_lines*((column->header)->nb_elements_per_line); + start = first_line_nb*((column->header)->nb_elements_per_line); end = start + nb_elements; switch ((column->header)->stored_data_type) { @@ -1476,35 +1447,3 @@ char* obi_column_format_date(time_t date) return formatted_time; } - -// TODO put in separate file ? -// warning for the dependency and for the fact that it's always added at the next line (or not cuz might not be a good idea?) -int obi_grep_line(OBIDMS_column_p referring_column, index_t line_to_grep) -{ - // Check that the column is referring another - if (!((referring_column->header)->referring)) - { - obi_set_errno(OBICOL_UNKNOWN_ERROR); - obidebug(1, "\nError: Grepping a line can only be done with a referring column"); - return -1; - } - - // Check if the file needs to be enlarged - if ((referring_column->header)->lines_used == (referring_column->header)->line_count) - { - // Enlarge the file - if (obi_enlarge_column(referring_column) < 0) - return -1; - } - - // Set the value - *(((index_t*) (referring_column->data)) + (referring_column->header)->lines_used) = line_to_grep; - - // Update lines used - ((referring_column->header)->lines_used)++; - - return 0; -} - - - diff --git a/src/obidmscolumn.h b/src/obidmscolumn.h index e295ccf..c5d355b 100644 --- a/src/obidmscolumn.h +++ b/src/obidmscolumn.h @@ -57,11 +57,7 @@ typedef struct OBIDMS_column_header { */ index_t lines_used; /**< Number of lines of data used. */ - index_t returned_nb_elements_per_line; /**< Number of elements per line returned when getting a - * line from the column. - */ - index_t stored_nb_elements_per_line; /**< Number of elements per line that is actually stored - * in the data part of the column. + index_t nb_elements_per_line; /**< Number of elements per line. */ char elements_names[ELEMENTS_NAMES_MAX+1]; /**< Names of the line elements with ';' as separator * (should be the column name if one element per line). @@ -80,10 +76,6 @@ typedef struct OBIDMS_column_header { * was cloned from (-1 if it was not created by cloning * another column). */ - bool referring; /**< Whether the column contains indices referring to another column. - */ - obiversion_t referred_column_version; /**< Version of the column to which this column is referring. - */ char name[OBIDMS_COLUMN_MAX_NAME+1]; /**< The column name as a NULL terminated string. */ char avl_name[AVL_MAX_NAME+1]; /**< If there is one, the AVL tree name as a NULL terminated string. @@ -108,14 +100,12 @@ typedef struct OBIDMS_column { */ OBIDMS_avl_p avl; /**< A pointer to the AVL tree associated with the column if there is one. */ - struct OBIDMS_column* referred_column; /**< A pointer to the referred column if the column is referring. - */ void* data; /**< A `void` pointer to the beginning of the data. * * @warning Never use this member directly outside of the code of the * low level functions of the OBIDMS. */ - bool writable; /**< Indicates if the column is writable or not. TODO delete? + bool writable; /**< Indicates if the column is writable or not. * - `true` the column is writable * - `false` the column is read-only * @@ -186,7 +176,6 @@ size_t obi_get_platform_header_size(); * @param elements_names The names of the elements with ';' as separator. * @param avl_name The name of the AVL tree if there is one associated with the column. * @param comments Optional comments associated with the column. - * @param referring * * @returns A pointer on the newly created column structure. * @retval NULL if an error occurred. @@ -201,8 +190,8 @@ OBIDMS_column_p obi_create_column(OBIDMS_p dms, index_t nb_elements_per_line, const char* elements_names, const char* avl_name, - const char* comments, - bool referring); + const char* comments + ); /** @@ -235,7 +224,7 @@ OBIDMS_column_p obi_open_column(OBIDMS_p dms, const char* column_name, obiversio * @since August 2015 * @author Celine Mercier (celine.mercier@metabarcoding.org) */ -OBIDMS_column_p obi_clone_column(OBIDMS_p dms, const char* column_name, obiversion_t version_number, bool referring, bool clone_data); +OBIDMS_column_p obi_clone_column(OBIDMS_p dms, OBIDMS_column_p line_selection, const char* column_name, obiversion_t version_number, bool clone_data); /** @@ -372,7 +361,7 @@ index_t obi_column_get_element_index_from_name(OBIDMS_column_p column, const cha char* obi_column_format_date(time_t date); -int obi_grep_line(OBIDMS_column_p referring_column, index_t line_to_grep); +int obi_select(OBIDMS_column_p lines_column, index_t line_to_grep); diff --git a/src/obidmscolumn_bool.c b/src/obidmscolumn_bool.c index 8817565..a781311 100644 --- a/src/obidmscolumn_bool.c +++ b/src/obidmscolumn_bool.c @@ -14,6 +14,7 @@ #include #include "obidmscolumn.h" +#include "obiview.h" #include "obitypes.h" #include "obierrno.h" #include "obidebug.h" @@ -28,16 +29,9 @@ * **********************************************************************/ + int obi_column_set_obibool_with_elt_idx(OBIDMS_column_p column, index_t line_nb, index_t element_idx, obibool_t value) { - // Check that the column is not referring another - if ((column->header)->referring) - { - obi_set_errno(OBICOL_UNKNOWN_ERROR); - obidebug(1, "\nError: Setting a value from a referring column is not allowed. The referred column must be cloned to be modified"); - return -1; - } - // Check that the line number is not greater than the maximum allowed if (line_nb >= MAXIMUM_LINE_COUNT) { @@ -59,7 +53,44 @@ int obi_column_set_obibool_with_elt_idx(OBIDMS_column_p column, index_t line_nb, (column->header)->lines_used = line_nb+1; // Set the value - *(((obibool_t*) (column->data)) + (line_nb * ((column->header)->stored_nb_elements_per_line)) + element_idx) = value; + *(((obibool_t*) (column->data)) + (line_nb * ((column->header)->nb_elements_per_line)) + element_idx) = value; + + return 0; +} + + +int obi_column_set_obibool_with_elt_idx_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx, obibool_t value) +{ + // Check that the view is not read-only + if (view->read_only) + { + obi_set_errno(OBIVIEW_ERROR); + obidebug(1, "\nError trying to set a value in a column in a read-only view"); + return -1; + } + + if ((view->line_selection != NULL) || (!(column->writable))) + { + // Get the right line number + if (column->writable) + line_nb = *(((index_t*) ((view->line_selection)->data)) + line_nb); + + column = obi_view_clone_column(view, (column->header)->name); + if (column == NULL) + { + obidebug(1, "\nError trying to clone a column to modify it"); + return -1; + } + } + + if ((line_nb+1) > view->line_count) + { + if (obi_view_update_lines(view, (line_nb+1)) < 0) + return -1; + } + + if (obi_column_set_obibool_with_elt_idx(column, line_nb, element_idx, value) < 0) + return -1; return 0; } @@ -67,22 +98,30 @@ int obi_column_set_obibool_with_elt_idx(OBIDMS_column_p column, index_t line_nb, obibool_t obi_column_get_obibool_with_elt_idx(OBIDMS_column_p column, index_t line_nb, index_t element_idx) { - index_t referring_idx; - - if ((line_nb+1) > (column->header)->lines_used) + if ((line_nb+1) > ((column->header)->line_count)) { obi_set_errno(OBICOL_UNKNOWN_ERROR); - obidebug(1, "\nError trying to get a value that is beyond the current number of lines used"); + obidebug(1, "\nError trying to get a value that is beyond the current number of lines used in the column"); return OBIBool_NA; } - if ((column->header)->referring) + return *(((obibool_t*) (column->data)) + (line_nb * ((column->header)->nb_elements_per_line)) + element_idx); +} + + +obibool_t obi_column_get_obibool_with_elt_idx_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx) +{ + if ((line_nb+1) > (view->line_count)) { - referring_idx = *(((index_t*) (column->data)) + line_nb); - return *(((obibool_t*) ((column->referred_column)->data)) + (referring_idx * ((column->header)->returned_nb_elements_per_line)) + element_idx); + obi_set_errno(OBICOL_UNKNOWN_ERROR); + obidebug(1, "\nError trying to get a value that is beyond the current line count of the view"); + return OBIBool_NA; } - else - return *(((obibool_t*) (column->data)) + (line_nb * ((column->header)->stored_nb_elements_per_line)) + element_idx); + + if (view->line_selection) + line_nb = *(((index_t*) ((view->line_selection)->data)) + line_nb); + + return obi_column_get_obibool_with_elt_idx(column, line_nb, element_idx); } @@ -97,6 +136,17 @@ int obi_column_set_obibool_with_elt_name(OBIDMS_column_p column, index_t line_nb } +int obi_column_set_obibool_with_elt_name_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name, obibool_t value) +{ + index_t element_idx; + element_idx = obi_column_get_element_index_from_name(column, element_name); + if (element_idx == OBIIdx_NA) + return -1; + obi_column_set_obibool_with_elt_idx_in_view(view, column, line_nb, element_idx, value); + return 0; +} + + obibool_t obi_column_get_obibool_with_elt_name(OBIDMS_column_p column, index_t line_nb, const char* element_name) { index_t element_idx; @@ -107,3 +157,13 @@ obibool_t obi_column_get_obibool_with_elt_name(OBIDMS_column_p column, index_t l return obi_column_get_obibool_with_elt_idx(column, line_nb, element_idx); } + +obibool_t obi_column_get_obibool_with_elt_name_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name) +{ + index_t element_idx; + + element_idx = obi_column_get_element_index_from_name(column, element_name); + if (element_idx == OBIIdx_NA) + return OBIBool_NA; + return obi_column_get_obibool_with_elt_idx_in_view(view, column, line_nb, element_idx); +} diff --git a/src/obidmscolumn_bool.h b/src/obidmscolumn_bool.h index deeaffc..254d43b 100644 --- a/src/obidmscolumn_bool.h +++ b/src/obidmscolumn_bool.h @@ -19,6 +19,7 @@ #include "obidmscolumn.h" #include "obitypes.h" +#include "obiview.h" /** @@ -38,7 +39,7 @@ * @since July 2015 * @author Celine Mercier (celine.mercier@metabarcoding.org) */ -int obi_column_set_obibool_with_elt_idx(OBIDMS_column_p column, index_t line_nb, size_t element_idx, obibool_t value); +int obi_column_set_obibool_with_elt_idx(OBIDMS_column_p column, index_t line_nb, index_t element_idx, obibool_t value); /** @@ -54,7 +55,7 @@ int obi_column_set_obibool_with_elt_idx(OBIDMS_column_p column, index_t line_nb, * @since July 2015 * @author Celine Mercier (celine.mercier@metabarcoding.org) */ -obibool_t obi_column_get_obibool_with_elt_idx(OBIDMS_column_p column, index_t line_nb, size_t element_idx); +obibool_t obi_column_get_obibool_with_elt_idx(OBIDMS_column_p column, index_t line_nb, index_t element_idx); /** @@ -95,5 +96,79 @@ int obi_column_set_obibool_with_elt_name(OBIDMS_column_p column, index_t line_nb obibool_t obi_column_get_obibool_with_elt_name(OBIDMS_column_p column, index_t line_nb, const char* element_name); +/** + * @brief Sets a value in an OBIDMS column containing data with the type OBI_BOOL, using the index of the element in the line. + * + * @warning Pointers returned by obi_open_column() don't allow writing. + * + * @param column A pointer as returned by obi_create_column() or obi_clone_column(). + * @param line_nb The number of the line where the value should be set. + * @param element_idx The index of the element that should be set in the line. + * @param value The value that should be set. + * + * @returns An integer value indicating the success of the operation. + * @retval 0 on success. + * @retval -1 if an error occurred. + * + * @since February 2016 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +int obi_column_set_obibool_with_elt_idx_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx, obibool_t value); + + +/** + * @brief Recovers a value in an OBIDMS column containing data with the type OBI_BOOL. + * + * @param column A pointer as returned by obi_create_column(). + * @param line_nb The number of the line where the value should be recovered. + * @param element_idx The index of the element that should be recovered in the line. + * + * @returns The recovered value. + * @retval OBIBool_NA the NA value of the type if an error occurred and obi_errno is set. + * + * @since February 2016 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +obibool_t obi_column_get_obibool_with_elt_idx_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx); + + +/** + * @brief Sets a value in an OBIDMS column containing data with the type OBI_BOOL, + * using the name of the element in the line. + * + * @warning Pointers returned by obi_open_column() don't allow writing. + * + * @param column A pointer as returned by obi_create_column() or obi_clone_column(). + * @param line_nb The number of the line where the value should be set. + * @param element_name The name of the element that should be set in the line. + * @param value The value that should be set. + * + * @returns An integer value indicating the success of the operation. + * @retval 0 on success. + * @retval -1 if an error occurred. + * + * @since February 2016 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +int obi_column_set_obibool_with_elt_name_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name, obibool_t value); + + +/** + * @brief Recovers a value in an OBIDMS column containing data with the type OBI_BOOL, + * using the name of the element in the line. + * + * @param column A pointer as returned by obi_create_column() or obi_clone_column(). + * @param line_nb The number of the line where the value should be recovered. + * @param element_name The name of the element that should be recovered in the line. + * + * @returns The recovered value. + * @retval OBIBool_NA the NA value of the type if an error occurred and obi_errno is set. + * + * @since February 2016 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +obibool_t obi_column_get_obibool_with_elt_name_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name); + + #endif /* OBIDMSCOLUMN_BOOL_H_ */ diff --git a/src/obidmscolumn_char.c b/src/obidmscolumn_char.c index 2e94187..361fb95 100644 --- a/src/obidmscolumn_char.c +++ b/src/obidmscolumn_char.c @@ -14,6 +14,7 @@ #include #include "obidmscolumn.h" +#include "obiview.h" #include "obitypes.h" #include "obierrno.h" #include "obidebug.h" @@ -28,16 +29,9 @@ * **********************************************************************/ + int obi_column_set_obichar_with_elt_idx(OBIDMS_column_p column, index_t line_nb, index_t element_idx, obichar_t value) { - // Check that the column is not referring another - if ((column->header)->referring) - { - obi_set_errno(OBICOL_UNKNOWN_ERROR); - obidebug(1, "\nError: Setting a value from a referring column is not allowed. The referred column must be cloned to be modified"); - return -1; - } - // Check that the line number is not greater than the maximum allowed if (line_nb >= MAXIMUM_LINE_COUNT) { @@ -59,7 +53,44 @@ int obi_column_set_obichar_with_elt_idx(OBIDMS_column_p column, index_t line_nb, (column->header)->lines_used = line_nb+1; // Set the value - *(((obichar_t*) (column->data)) + (line_nb * ((column->header)->stored_nb_elements_per_line)) + element_idx) = value; + *(((obichar_t*) (column->data)) + (line_nb * ((column->header)->nb_elements_per_line)) + element_idx) = value; + + return 0; +} + + +int obi_column_set_obichar_with_elt_idx_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx, obichar_t value) +{ + // Check that the view is not read-only + if (view->read_only) + { + obi_set_errno(OBIVIEW_ERROR); + obidebug(1, "\nError trying to set a value in a column in a read-only view"); + return -1; + } + + if ((view->line_selection != NULL) || (!(column->writable))) + { + // Get the right line number + if (column->writable) + line_nb = *(((index_t*) ((view->line_selection)->data)) + line_nb); + + column = obi_view_clone_column(view, (column->header)->name); + if (column == NULL) + { + obidebug(1, "\nError trying to clone a column to modify it"); + return -1; + } + } + + if ((line_nb+1) > view->line_count) + { + if (obi_view_update_lines(view, (line_nb+1)) < 0) + return -1; + } + + if (obi_column_set_obichar_with_elt_idx(column, line_nb, element_idx, value) < 0) + return -1; return 0; } @@ -67,22 +98,30 @@ int obi_column_set_obichar_with_elt_idx(OBIDMS_column_p column, index_t line_nb, obichar_t obi_column_get_obichar_with_elt_idx(OBIDMS_column_p column, index_t line_nb, index_t element_idx) { - index_t referring_idx; - - if ((line_nb+1) > (column->header)->lines_used) + if ((line_nb+1) > ((column->header)->line_count)) { obi_set_errno(OBICOL_UNKNOWN_ERROR); - obidebug(1, "\nError trying to get a value that is beyond the current number of lines used"); + obidebug(1, "\nError trying to get a value that is beyond the current number of lines used in the column"); return OBIChar_NA; } - if ((column->header)->referring) + return *(((obichar_t*) (column->data)) + (line_nb * ((column->header)->nb_elements_per_line)) + element_idx); +} + + +obichar_t obi_column_get_obichar_with_elt_idx_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx) +{ + if ((line_nb+1) > (view->line_count)) { - referring_idx = *(((index_t*) (column->data)) + line_nb); - return *(((obichar_t*) ((column->referred_column)->data)) + (referring_idx * ((column->header)->returned_nb_elements_per_line)) + element_idx); + obi_set_errno(OBICOL_UNKNOWN_ERROR); + obidebug(1, "\nError trying to get a value that is beyond the current line count of the view"); + return OBIChar_NA; } - else - return *(((obichar_t*) (column->data)) + (line_nb * ((column->header)->stored_nb_elements_per_line)) + element_idx); + + if (view->line_selection) + line_nb = *(((index_t*) ((view->line_selection)->data)) + line_nb); + + return obi_column_get_obichar_with_elt_idx(column, line_nb, element_idx); } @@ -97,6 +136,17 @@ int obi_column_set_obichar_with_elt_name(OBIDMS_column_p column, index_t line_nb } +int obi_column_set_obichar_with_elt_name_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name, obichar_t value) +{ + index_t element_idx; + element_idx = obi_column_get_element_index_from_name(column, element_name); + if (element_idx == OBIIdx_NA) + return -1; + obi_column_set_obichar_with_elt_idx_in_view(view, column, line_nb, element_idx, value); + return 0; +} + + obichar_t obi_column_get_obichar_with_elt_name(OBIDMS_column_p column, index_t line_nb, const char* element_name) { index_t element_idx; @@ -107,3 +157,13 @@ obichar_t obi_column_get_obichar_with_elt_name(OBIDMS_column_p column, index_t l return obi_column_get_obichar_with_elt_idx(column, line_nb, element_idx); } + +obichar_t obi_column_get_obichar_with_elt_name_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name) +{ + index_t element_idx; + + element_idx = obi_column_get_element_index_from_name(column, element_name); + if (element_idx == OBIIdx_NA) + return OBIChar_NA; + return obi_column_get_obichar_with_elt_idx_in_view(view, column, line_nb, element_idx); +} diff --git a/src/obidmscolumn_char.h b/src/obidmscolumn_char.h index ed2f7fc..639023e 100644 --- a/src/obidmscolumn_char.h +++ b/src/obidmscolumn_char.h @@ -19,6 +19,7 @@ #include "obidmscolumn.h" #include "obitypes.h" +#include "obiview.h" /** @@ -49,7 +50,7 @@ int obi_column_set_obichar_with_elt_idx(OBIDMS_column_p column, index_t line_nb, * @param element_idx The index of the element that should be recovered in the line. * * @returns The recovered value. - * @retval OBIBool_NA the NA value of the type if an error occurred and obi_errno is set. + * @retval OBIChar_NA the NA value of the type if an error occurred and obi_errno is set. * * @since July 2015 * @author Celine Mercier (celine.mercier@metabarcoding.org) @@ -87,7 +88,7 @@ int obi_column_set_obichar_with_elt_name(OBIDMS_column_p column, index_t line_nb * @param element_name The name of the element that should be recovered in the line. * * @returns The recovered value. - * @retval OBIBool_NA the NA value of the type if an error occurred and obi_errno is set. + * @retval OBIChar_NA the NA value of the type if an error occurred and obi_errno is set. * * @since August 2015 * @author Celine Mercier (celine.mercier@metabarcoding.org) @@ -95,5 +96,79 @@ int obi_column_set_obichar_with_elt_name(OBIDMS_column_p column, index_t line_nb obichar_t obi_column_get_obichar_with_elt_name(OBIDMS_column_p column, index_t line_nb, const char* element_name); +/** + * @brief Sets a value in an OBIDMS column containing data with the type OBI_CHAR, using the index of the element in the line. + * + * @warning Pointers returned by obi_open_column() don't allow writing. + * + * @param column A pointer as returned by obi_create_column() or obi_clone_column(). + * @param line_nb The number of the line where the value should be set. + * @param element_idx The index of the element that should be set in the line. + * @param value The value that should be set. + * + * @returns An integer value indicating the success of the operation. + * @retval 0 on success. + * @retval -1 if an error occurred. + * + * @since February 2016 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +int obi_column_set_obichar_with_elt_idx_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx, obichar_t value); + + +/** + * @brief Recovers a value in an OBIDMS column containing data with the type OBI_CHAR. + * + * @param column A pointer as returned by obi_create_column(). + * @param line_nb The number of the line where the value should be recovered. + * @param element_idx The index of the element that should be recovered in the line. + * + * @returns The recovered value. + * @retval OBIChar_NA the NA value of the type if an error occurred and obi_errno is set. + * + * @since February 2016 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +obichar_t obi_column_get_obichar_with_elt_idx_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx); + + +/** + * @brief Sets a value in an OBIDMS column containing data with the type OBI_CHAR, + * using the name of the element in the line. + * + * @warning Pointers returned by obi_open_column() don't allow writing. + * + * @param column A pointer as returned by obi_create_column() or obi_clone_column(). + * @param line_nb The number of the line where the value should be set. + * @param element_name The name of the element that should be set in the line. + * @param value The value that should be set. + * + * @returns An integer value indicating the success of the operation. + * @retval 0 on success. + * @retval -1 if an error occurred. + * + * @since February 2016 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +int obi_column_set_obichar_with_elt_name_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name, obichar_t value); + + +/** + * @brief Recovers a value in an OBIDMS column containing data with the type OBI_CHAR, + * using the name of the element in the line. + * + * @param column A pointer as returned by obi_create_column() or obi_clone_column(). + * @param line_nb The number of the line where the value should be recovered. + * @param element_name The name of the element that should be recovered in the line. + * + * @returns The recovered value. + * @retval OBIChar_NA the NA value of the type if an error occurred and obi_errno is set. + * + * @since February 2016 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +obichar_t obi_column_get_obichar_with_elt_name_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name); + + #endif /* OBIDMSCOLUMN_CHAR_H_ */ diff --git a/src/obidmscolumn_float.c b/src/obidmscolumn_float.c index d927235..6ecfe3c 100644 --- a/src/obidmscolumn_float.c +++ b/src/obidmscolumn_float.c @@ -14,6 +14,7 @@ #include #include "obidmscolumn.h" +#include "obiview.h" #include "obitypes.h" #include "obierrno.h" #include "obidebug.h" @@ -30,14 +31,6 @@ int obi_column_set_obifloat_with_elt_idx(OBIDMS_column_p column, index_t line_nb, index_t element_idx, obifloat_t value) { - // Check that the column is not referring another - if ((column->header)->referring) - { - obi_set_errno(OBICOL_UNKNOWN_ERROR); - obidebug(1, "\nError: Setting a value from a referring column is not allowed. The referred column must be cloned to be modified"); - return -1; - } - // Check that the line number is not greater than the maximum allowed if (line_nb >= MAXIMUM_LINE_COUNT) { @@ -59,7 +52,44 @@ int obi_column_set_obifloat_with_elt_idx(OBIDMS_column_p column, index_t line_nb (column->header)->lines_used = line_nb+1; // Set the value - *(((obifloat_t*) (column->data)) + (line_nb * ((column->header)->stored_nb_elements_per_line)) + element_idx) = value; + *(((obifloat_t*) (column->data)) + (line_nb * ((column->header)->nb_elements_per_line)) + element_idx) = value; + + return 0; +} + + +int obi_column_set_obifloat_with_elt_idx_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx, obifloat_t value) +{ + // Check that the view is not read-only + if (view->read_only) + { + obi_set_errno(OBIVIEW_ERROR); + obidebug(1, "\nError trying to set a value in a column in a read-only view"); + return -1; + } + + if ((view->line_selection != NULL) || (!(column->writable))) + { + // Get the right line number + if (column->writable) + line_nb = *(((index_t*) ((view->line_selection)->data)) + line_nb); + + column = obi_view_clone_column(view, (column->header)->name); + if (column == NULL) + { + obidebug(1, "\nError trying to clone a column to modify it"); + return -1; + } + } + + if ((line_nb+1) > view->line_count) + { + if (obi_view_update_lines(view, (line_nb+1)) < 0) + return -1; + } + + if (obi_column_set_obifloat_with_elt_idx(column, line_nb, element_idx, value) < 0) + return -1; return 0; } @@ -67,22 +97,30 @@ int obi_column_set_obifloat_with_elt_idx(OBIDMS_column_p column, index_t line_nb obifloat_t obi_column_get_obifloat_with_elt_idx(OBIDMS_column_p column, index_t line_nb, index_t element_idx) { - index_t referring_idx; - - if ((line_nb+1) > (column->header)->lines_used) + if ((line_nb+1) > ((column->header)->line_count)) { obi_set_errno(OBICOL_UNKNOWN_ERROR); - obidebug(1, "\nError trying to get a value that is beyond the current number of lines used"); + obidebug(1, "\nError trying to get a value that is beyond the current number of lines used in the column"); return OBIFloat_NA; } - if ((column->header)->referring) + return *(((obifloat_t*) (column->data)) + (line_nb * ((column->header)->nb_elements_per_line)) + element_idx); +} + + +obifloat_t obi_column_get_obifloat_with_elt_idx_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx) +{ + if ((line_nb+1) > (view->line_count)) { - referring_idx = *(((index_t*) (column->data)) + line_nb); - return *(((obifloat_t*) ((column->referred_column)->data)) + (referring_idx * ((column->header)->returned_nb_elements_per_line)) + element_idx); + obi_set_errno(OBICOL_UNKNOWN_ERROR); + obidebug(1, "\nError trying to get a value that is beyond the current line count of the view"); + return OBIFloat_NA; } - else - return *(((obifloat_t*) (column->data)) + (line_nb * ((column->header)->stored_nb_elements_per_line)) + element_idx); + + if (view->line_selection) + line_nb = *(((index_t*) ((view->line_selection)->data)) + line_nb); + + return obi_column_get_obifloat_with_elt_idx(column, line_nb, element_idx); } @@ -97,6 +135,17 @@ int obi_column_set_obifloat_with_elt_name(OBIDMS_column_p column, index_t line_n } +int obi_column_set_obifloat_with_elt_name_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name, obifloat_t value) +{ + index_t element_idx; + element_idx = obi_column_get_element_index_from_name(column, element_name); + if (element_idx == OBIIdx_NA) + return -1; + obi_column_set_obifloat_with_elt_idx_in_view(view, column, line_nb, element_idx, value); + return 0; +} + + obifloat_t obi_column_get_obifloat_with_elt_name(OBIDMS_column_p column, index_t line_nb, const char* element_name) { index_t element_idx; @@ -107,3 +156,13 @@ obifloat_t obi_column_get_obifloat_with_elt_name(OBIDMS_column_p column, index_t return obi_column_get_obifloat_with_elt_idx(column, line_nb, element_idx); } + +obifloat_t obi_column_get_obifloat_with_elt_name_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name) +{ + index_t element_idx; + + element_idx = obi_column_get_element_index_from_name(column, element_name); + if (element_idx == OBIIdx_NA) + return OBIFloat_NA; + return obi_column_get_obifloat_with_elt_idx_in_view(view, column, line_nb, element_idx); +} diff --git a/src/obidmscolumn_float.h b/src/obidmscolumn_float.h index 407c34f..5a03b2e 100644 --- a/src/obidmscolumn_float.h +++ b/src/obidmscolumn_float.h @@ -19,6 +19,7 @@ #include "obidmscolumn.h" #include "obitypes.h" +#include "obiview.h" /** @@ -49,7 +50,7 @@ int obi_column_set_obifloat_with_elt_idx(OBIDMS_column_p column, index_t line_nb * @param element_idx The index of the element that should be recovered in the line. * * @returns The recovered value. - * @retval OBIBool_NA the NA value of the type if an error occurred and obi_errno is set. + * @retval OBIFloat_NA the NA value of the type if an error occurred and obi_errno is set. * * @since July 2015 * @author Celine Mercier (celine.mercier@metabarcoding.org) @@ -87,7 +88,7 @@ int obi_column_set_obifloat_with_elt_name(OBIDMS_column_p column, index_t line_n * @param element_name The name of the element that should be recovered in the line. * * @returns The recovered value. - * @retval OBIBool_NA the NA value of the type if an error occurred and obi_errno is set. + * @retval OBIFloat_NA the NA value of the type if an error occurred and obi_errno is set. * * @since August 2015 * @author Celine Mercier (celine.mercier@metabarcoding.org) @@ -95,5 +96,79 @@ int obi_column_set_obifloat_with_elt_name(OBIDMS_column_p column, index_t line_n obifloat_t obi_column_get_obifloat_with_elt_name(OBIDMS_column_p column, index_t line_nb, const char* element_name); +/** + * @brief Sets a value in an OBIDMS column containing data with the type OBI_FLOAT, using the index of the element in the line. + * + * @warning Pointers returned by obi_open_column() don't allow writing. + * + * @param column A pointer as returned by obi_create_column() or obi_clone_column(). + * @param line_nb The number of the line where the value should be set. + * @param element_idx The index of the element that should be set in the line. + * @param value The value that should be set. + * + * @returns An integer value indicating the success of the operation. + * @retval 0 on success. + * @retval -1 if an error occurred. + * + * @since February 2016 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +int obi_column_set_obifloat_with_elt_idx_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx, obifloat_t value); + + +/** + * @brief Recovers a value in an OBIDMS column containing data with the type OBI_FLOAT. + * + * @param column A pointer as returned by obi_create_column(). + * @param line_nb The number of the line where the value should be recovered. + * @param element_idx The index of the element that should be recovered in the line. + * + * @returns The recovered value. + * @retval OBIFloat_NA the NA value of the type if an error occurred and obi_errno is set. + * + * @since February 2016 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +obifloat_t obi_column_get_obifloat_with_elt_idx_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx); + + +/** + * @brief Sets a value in an OBIDMS column containing data with the type OBI_FLOAT, + * using the name of the element in the line. + * + * @warning Pointers returned by obi_open_column() don't allow writing. + * + * @param column A pointer as returned by obi_create_column() or obi_clone_column(). + * @param line_nb The number of the line where the value should be set. + * @param element_name The name of the element that should be set in the line. + * @param value The value that should be set. + * + * @returns An integer value indicating the success of the operation. + * @retval 0 on success. + * @retval -1 if an error occurred. + * + * @since February 2016 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +int obi_column_set_obifloat_with_elt_name_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name, obifloat_t value); + + +/** + * @brief Recovers a value in an OBIDMS column containing data with the type OBI_FLOAT, + * using the name of the element in the line. + * + * @param column A pointer as returned by obi_create_column() or obi_clone_column(). + * @param line_nb The number of the line where the value should be recovered. + * @param element_name The name of the element that should be recovered in the line. + * + * @returns The recovered value. + * @retval OBIFloat_NA the NA value of the type if an error occurred and obi_errno is set. + * + * @since February 2016 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +obifloat_t obi_column_get_obifloat_with_elt_name_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name); + + #endif /* OBIDMSCOLUMN_FLOAT_H_ */ diff --git a/src/obidmscolumn_idx.c b/src/obidmscolumn_idx.c new file mode 100644 index 0000000..95ddadb --- /dev/null +++ b/src/obidmscolumn_idx.c @@ -0,0 +1,72 @@ +/**************************************************************************** + * OBIDMS_column_idx functions * + ****************************************************************************/ + +/** + * @file obidsmcolumn_idx.c + * @author Celine Mercier + * @date February 14th 2016 + * @brief Functions handling OBIColumns containing data with the index_t type. + */ + + +#include +#include + +#include "obidmscolumn.h" +#include "obitypes.h" +#include "obierrno.h" +#include "obidebug.h" + + +#define DEBUG_LEVEL 0 // TODO has to be defined somewhere else (cython compil flag?) + + +/********************************************************************** + * + * D E F I N I T I O N O F T H E P U B L I C F U N C T I O N S + * + **********************************************************************/ + + +int obi_column_set_index(OBIDMS_column_p column, index_t line_nb, index_t value) +{ + // Check that the line number is not greater than the maximum allowed + if (line_nb >= MAXIMUM_LINE_COUNT) + { + obi_set_errno(OBICOL_UNKNOWN_ERROR); + obidebug(1, "\nError trying to set a value at a line number greater than the maximum allowed"); + return -1; + } + + // Check if the file needs to be enlarged + while ((line_nb+1) > (column->header)->line_count) + { + // Enlarge the file + if (obi_enlarge_column(column) < 0) + return -1; + } + + // Update lines used + if ((line_nb+1) > (column->header)->lines_used) + (column->header)->lines_used = line_nb+1; + + // Set the value + *(((index_t*) (column->data)) + line_nb) = value; + + return 0; +} + + +index_t obi_column_get_index(OBIDMS_column_p column, index_t line_nb) +{ + if ((line_nb+1) > ((column->header)->line_count)) + { + obi_set_errno(OBICOL_UNKNOWN_ERROR); + obidebug(1, "\nError trying to get a value that is beyond the current number of lines used in the column"); + return OBIIdx_NA; + } + + return *(((index_t*) (column->data)) + line_nb); +} + diff --git a/src/obidmscolumn_idx.h b/src/obidmscolumn_idx.h new file mode 100644 index 0000000..326318a --- /dev/null +++ b/src/obidmscolumn_idx.h @@ -0,0 +1,30 @@ +/**************************************************************************** + * OBIDMS_column_idx header file * + ****************************************************************************/ + +/** + * @file obidsmcolumn_idx.h + * @author Celine Mercier + * @date February 14th 2016 + * @brief Header file for the functions handling OBIColumns containing data with the OBIType OBI_IDX. + */ + + +#ifndef OBIDMSCOLUMN_IDX_H_ +#define OBIDMSCOLUMN_IDX_H_ + + +#include +#include + +#include "obidmscolumn.h" +#include "obitypes.h" + + +int obi_column_set_index(OBIDMS_column_p column, index_t line_nb, index_t value); + +index_t obi_column_get_index(OBIDMS_column_p column, index_t line_nb); + + +#endif /* OBIDMSCOLUMN_IDX_H_ */ + diff --git a/src/obidmscolumn_int.c b/src/obidmscolumn_int.c index 2e9aa5e..93e66b2 100644 --- a/src/obidmscolumn_int.c +++ b/src/obidmscolumn_int.c @@ -14,6 +14,7 @@ #include #include "obidmscolumn.h" +#include "obiview.h" #include "obitypes.h" #include "obierrno.h" #include "obidebug.h" @@ -28,16 +29,9 @@ * **********************************************************************/ + int obi_column_set_obiint_with_elt_idx(OBIDMS_column_p column, index_t line_nb, index_t element_idx, obiint_t value) { - // Check that the column is not referring another - if ((column->header)->referring) - { - obi_set_errno(OBICOL_UNKNOWN_ERROR); - obidebug(1, "\nError: Setting a value from a referring column is not allowed. The referred column must be cloned to be modified"); - return -1; - } - // Check that the line number is not greater than the maximum allowed if (line_nb >= MAXIMUM_LINE_COUNT) { @@ -59,7 +53,44 @@ int obi_column_set_obiint_with_elt_idx(OBIDMS_column_p column, index_t line_nb, (column->header)->lines_used = line_nb+1; // Set the value - *(((obiint_t*) (column->data)) + (line_nb * ((column->header)->stored_nb_elements_per_line)) + element_idx) = value; + *(((obiint_t*) (column->data)) + (line_nb * ((column->header)->nb_elements_per_line)) + element_idx) = value; + + return 0; +} + + +int obi_column_set_obiint_with_elt_idx_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx, obiint_t value) +{ + // Check that the view is not read-only + if (view->read_only) + { + obi_set_errno(OBIVIEW_ERROR); + obidebug(1, "\nError trying to set a value in a column in a read-only view"); + return -1; + } + + if ((view->line_selection != NULL) || (!(column->writable))) + { + // Get the right line number + if (column->writable) + line_nb = *(((index_t*) ((view->line_selection)->data)) + line_nb); + + column = obi_view_clone_column(view, (column->header)->name); + if (column == NULL) + { + obidebug(1, "\nError trying to clone a column to modify it"); + return -1; + } + } + + if ((line_nb+1) > view->line_count) + { + if (obi_view_update_lines(view, (line_nb+1)) < 0) + return -1; + } + + if (obi_column_set_obiint_with_elt_idx(column, line_nb, element_idx, value) < 0) + return -1; return 0; } @@ -67,22 +98,30 @@ int obi_column_set_obiint_with_elt_idx(OBIDMS_column_p column, index_t line_nb, obiint_t obi_column_get_obiint_with_elt_idx(OBIDMS_column_p column, index_t line_nb, index_t element_idx) { - index_t referring_idx; - - if ((line_nb+1) > (column->header)->lines_used) + if ((line_nb+1) > ((column->header)->line_count)) { obi_set_errno(OBICOL_UNKNOWN_ERROR); - obidebug(1, "\nError trying to get a value that is beyond the current number of lines used"); + obidebug(1, "\nError trying to get a value that is beyond the current number of lines used in the column"); return OBIInt_NA; } - if ((column->header)->referring) + return *(((obiint_t*) (column->data)) + (line_nb * ((column->header)->nb_elements_per_line)) + element_idx); +} + + +obiint_t obi_column_get_obiint_with_elt_idx_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx) +{ + if ((line_nb+1) > (view->line_count)) { - referring_idx = *(((index_t*) (column->data)) + line_nb); - return *(((obiint_t*) ((column->referred_column)->data)) + (referring_idx * ((column->header)->returned_nb_elements_per_line)) + element_idx); + obi_set_errno(OBICOL_UNKNOWN_ERROR); + obidebug(1, "\nError trying to get a value that is beyond the current line count of the view"); + return OBIInt_NA; } - else - return *(((obiint_t*) (column->data)) + (line_nb * ((column->header)->stored_nb_elements_per_line)) + element_idx); + + if (view->line_selection) + line_nb = *(((index_t*) ((view->line_selection)->data)) + line_nb); + + return obi_column_get_obiint_with_elt_idx(column, line_nb, element_idx); } @@ -97,6 +136,17 @@ int obi_column_set_obiint_with_elt_name(OBIDMS_column_p column, index_t line_nb, } +int obi_column_set_obiint_with_elt_name_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name, obiint_t value) +{ + index_t element_idx; + element_idx = obi_column_get_element_index_from_name(column, element_name); + if (element_idx == OBIIdx_NA) + return -1; + obi_column_set_obiint_with_elt_idx_in_view(view, column, line_nb, element_idx, value); + return 0; +} + + obiint_t obi_column_get_obiint_with_elt_name(OBIDMS_column_p column, index_t line_nb, const char* element_name) { index_t element_idx; @@ -107,3 +157,14 @@ obiint_t obi_column_get_obiint_with_elt_name(OBIDMS_column_p column, index_t lin return obi_column_get_obiint_with_elt_idx(column, line_nb, element_idx); } + +obiint_t obi_column_get_obiint_with_elt_name_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name) +{ + index_t element_idx; + + element_idx = obi_column_get_element_index_from_name(column, element_name); + if (element_idx == OBIIdx_NA) + return OBIInt_NA; + return obi_column_get_obiint_with_elt_idx_in_view(view, column, line_nb, element_idx); +} + diff --git a/src/obidmscolumn_int.h b/src/obidmscolumn_int.h index 3e6f600..afe52ee 100644 --- a/src/obidmscolumn_int.h +++ b/src/obidmscolumn_int.h @@ -19,6 +19,7 @@ #include "obidmscolumn.h" #include "obitypes.h" +#include "obiview.h" /** @@ -95,5 +96,79 @@ int obi_column_set_obiint_with_elt_name(OBIDMS_column_p column, index_t line_nb, obiint_t obi_column_get_obiint_with_elt_name(OBIDMS_column_p column, index_t line_nb, const char* element_name); +/** + * @brief Sets a value in an OBIDMS column containing data with the type OBI_INT, using the index of the element in the line. + * + * @warning Pointers returned by obi_open_column() don't allow writing. + * + * @param column A pointer as returned by obi_create_column() or obi_clone_column(). + * @param line_nb The number of the line where the value should be set. + * @param element_idx The index of the element that should be set in the line. + * @param value The value that should be set. + * + * @returns An integer value indicating the success of the operation. + * @retval 0 on success. + * @retval -1 if an error occurred. + * + * @since February 2016 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +int obi_column_set_obiint_with_elt_idx_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx, obiint_t value); + + +/** + * @brief Recovers a value in an OBIDMS column containing data with the type OBI_INT. + * + * @param column A pointer as returned by obi_create_column(). + * @param line_nb The number of the line where the value should be recovered. + * @param element_idx The index of the element that should be recovered in the line. + * + * @returns The recovered value. + * @retval OBIBool_NA the NA value of the type if an error occurred and obi_errno is set. + * + * @since February 2016 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +obiint_t obi_column_get_obiint_with_elt_idx_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx); + + +/** + * @brief Sets a value in an OBIDMS column containing data with the type OBI_INT, + * using the name of the element in the line. + * + * @warning Pointers returned by obi_open_column() don't allow writing. + * + * @param column A pointer as returned by obi_create_column() or obi_clone_column(). + * @param line_nb The number of the line where the value should be set. + * @param element_name The name of the element that should be set in the line. + * @param value The value that should be set. + * + * @returns An integer value indicating the success of the operation. + * @retval 0 on success. + * @retval -1 if an error occurred. + * + * @since February 2016 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +int obi_column_set_obiint_with_elt_name_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name, obiint_t value); + + +/** + * @brief Recovers a value in an OBIDMS column containing data with the type OBI_INT, + * using the name of the element in the line. + * + * @param column A pointer as returned by obi_create_column() or obi_clone_column(). + * @param line_nb The number of the line where the value should be recovered. + * @param element_name The name of the element that should be recovered in the line. + * + * @returns The recovered value. + * @retval OBIBool_NA the NA value of the type if an error occurred and obi_errno is set. + * + * @since February 2016 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +obiint_t obi_column_get_obiint_with_elt_name_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name); + + #endif /* OBIDMSCOLUMN_INT_H_ */ diff --git a/src/obidmscolumn_seq.c b/src/obidmscolumn_seq.c index beabf51..789b859 100644 --- a/src/obidmscolumn_seq.c +++ b/src/obidmscolumn_seq.c @@ -14,6 +14,7 @@ #include #include "obidmscolumn.h" +#include "obiview.h" #include "obitypes.h" #include "obierrno.h" #include "obidebug.h" @@ -29,19 +30,12 @@ * **********************************************************************/ + int obi_column_set_obiseq_with_elt_idx(OBIDMS_column_p column, index_t line_nb, index_t element_idx, char* value) { byte_t* value_b; index_t idx; - // Check that the column is not referring another - if ((column->header)->referring) - { - obi_set_errno(OBICOL_UNKNOWN_ERROR); - obidebug(1, "\nError: Setting a value from a referring column is not allowed. The referred column must be cloned to be modified"); - return -1; - } - // Check that the line number is not greater than the maximum allowed if (line_nb >= MAXIMUM_LINE_COUNT) { @@ -73,7 +67,7 @@ int obi_column_set_obiseq_with_elt_idx(OBIDMS_column_p column, index_t line_nb, return -1; // Add the value's index in the column - *(((index_t*) (column->data)) + (line_nb * ((column->header)->stored_nb_elements_per_line)) + element_idx) = idx; + *(((index_t*) (column->data)) + (line_nb * ((column->header)->nb_elements_per_line)) + element_idx) = idx; free(value_b); @@ -81,44 +75,100 @@ int obi_column_set_obiseq_with_elt_idx(OBIDMS_column_p column, index_t line_nb, } +int obi_column_set_obiseq_with_elt_idx_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx, char* value) +{ + // Check that the view is not read-only + if (view->read_only) + { + obi_set_errno(OBIVIEW_ERROR); + obidebug(1, "\nError trying to set a value in a column in a read-only view"); + return -1; + } + + if ((view->line_selection != NULL) || (!(column->writable))) + { + // Get the right line number + if (column->writable) + line_nb = *(((index_t*) ((view->line_selection)->data)) + line_nb); + + column = obi_view_clone_column(view, (column->header)->name); + if (column == NULL) + { + obidebug(1, "\nError trying to clone a column to modify it"); + return -1; + } + } + + if ((line_nb+1) > view->line_count) + { + if (obi_view_update_lines(view, (line_nb+1)) < 0) + return -1; + } + + if (obi_column_set_obiseq_with_elt_idx(column, line_nb, element_idx, value) < 0) + return -1; + + return 0; +} + + const char* obi_column_get_obiseq_with_elt_idx(OBIDMS_column_p column, index_t line_nb, index_t element_idx) { index_t idx; byte_t* value_b; - index_t referring_idx; - if ((line_nb+1) > (column->header)->lines_used) + if ((line_nb+1) > ((column->header)->line_count)) { obi_set_errno(OBICOL_UNKNOWN_ERROR); - obidebug(1, "\nError trying to get a value that is beyond the current number of lines used"); - return "\0"; // TODO + obidebug(1, "\nError trying to get a value that is beyond the current number of lines used in the column"); + return OBISeq_NA; } - if ((column->header)->referring) - { - referring_idx = *(((index_t*) (column->data)) + line_nb); - idx = *(((index_t*) ((column->referred_column)->data)) + (referring_idx * ((column->header)->returned_nb_elements_per_line)) + element_idx); - } - else - idx = *(((index_t*) (column->data)) + (line_nb * ((column->header)->stored_nb_elements_per_line)) + element_idx); + idx = *(((index_t*) (column->data)) + (line_nb * ((column->header)->nb_elements_per_line)) + element_idx); // Check NA if (idx == OBIIdx_NA) - return "\0"; // TODO + return OBISeq_NA; value_b = obi_avl_get(column->avl, idx); return obi_obibytes_to_seq(value_b); } +const char* obi_column_get_obiseq_with_elt_idx_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx) +{ + if ((line_nb+1) > (view->line_count)) + { + obi_set_errno(OBICOL_UNKNOWN_ERROR); + obidebug(1, "\nError trying to get a value that is beyond the current line count of the view"); + return OBISeq_NA; + } + + if (view->line_selection) + line_nb = *(((index_t*) ((view->line_selection)->data)) + line_nb); + + return obi_column_get_obiseq_with_elt_idx(column, line_nb, element_idx); +} + + int obi_column_set_obiseq_with_elt_name(OBIDMS_column_p column, index_t line_nb, const char* element_name, char* value) { index_t element_idx; element_idx = obi_column_get_element_index_from_name(column, element_name); if (element_idx == OBIIdx_NA) return -1; - if (obi_column_set_obiseq_with_elt_idx(column, line_nb, element_idx, value) < 0) + obi_column_set_obiseq_with_elt_idx(column, line_nb, element_idx, value); + return 0; +} + + +int obi_column_set_obiseq_with_elt_name_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name, char* value) +{ + index_t element_idx; + element_idx = obi_column_get_element_index_from_name(column, element_name); + if (element_idx == OBIIdx_NA) return -1; + obi_column_set_obiseq_with_elt_idx_in_view(view, column, line_nb, element_idx, value); return 0; } @@ -129,7 +179,18 @@ const char* obi_column_get_obiseq_with_elt_name(OBIDMS_column_p column, index_t element_idx = obi_column_get_element_index_from_name(column, element_name); if (element_idx == OBIIdx_NA) - return "\0"; + return OBISeq_NA; return obi_column_get_obiseq_with_elt_idx(column, line_nb, element_idx); } + +const char* obi_column_get_obiseq_with_elt_name_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name) +{ + index_t element_idx; + + element_idx = obi_column_get_element_index_from_name(column, element_name); + if (element_idx == OBIIdx_NA) + return OBISeq_NA; + return obi_column_get_obiseq_with_elt_idx_in_view(view, column, line_nb, element_idx); +} + diff --git a/src/obidmscolumn_seq.h b/src/obidmscolumn_seq.h index ca934a2..e443a47 100644 --- a/src/obidmscolumn_seq.h +++ b/src/obidmscolumn_seq.h @@ -19,6 +19,7 @@ #include "obidmscolumn.h" #include "obitypes.h" +#include "obiview.h" /** @@ -97,5 +98,81 @@ int obi_column_set_obiseq_with_elt_name(OBIDMS_column_p column, index_t line_nb, const char* obi_column_get_obiseq_with_elt_name(OBIDMS_column_p column, index_t line_nb, const char* element_name); +/** + * @brief Sets a value in an OBIDMS column containing data in the form of indices referring + * to DNA sequences in an AVL tree, using the index of the element in the line. + * + * @warning Pointers returned by obi_open_column() don't allow writing. + * + * @param column A pointer as returned by obi_create_column() or obi_clone_column(). + * @param line_nb The number of the line where the value should be set. + * @param element_idx The index of the element that should be set in the line. + * @param value The value that should be set. + * + * @returns An integer value indicating the success of the operation. + * @retval 0 on success. + * @retval -1 if an error occurred. + * + * @since February 2016 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +int obi_column_set_obiseq_with_elt_idx_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx, char* value); + + +/** + * @brief Recovers a value in an OBIDMS column containing data in the form of indices referring + * to DNA sequences in an AVL tree, using the index of the element in the line. + * + * @param column A pointer as returned by obi_create_column(). + * @param line_nb The number of the line where the value should be recovered. + * @param element_idx The index of the element that should be recovered in the line. + * + * @returns The recovered value. + * @retval '\0' the NA value of the type if an error occurred and obi_errno is set. + * + * @since February 2016 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +const char* obi_column_get_obiseq_with_elt_idx_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx); + + +/** + * @brief Sets a value in an OBIDMS column containing data in the form of indices referring + * to DNA sequences in an AVL tree, using the name of the element in the line. + * + * @warning Pointers returned by obi_open_column() don't allow writing. + * + * @param column A pointer as returned by obi_create_column() or obi_clone_column(). + * @param line_nb The number of the line where the value should be set. + * @param element_name The name of the element that should be set in the line. + * @param value The value that should be set. + * + * @returns An integer value indicating the success of the operation. + * @retval 0 on success. + * @retval -1 if an error occurred. + * + * @since February 2016 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +int obi_column_set_obiseq_with_elt_name_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name, char* value); + + +/** + * @brief Recovers a value in an OBIDMS column containing data in the form of indices referring + * to DNA sequences in an AVL tree, using the name of the element in the line. + * + * @param column A pointer as returned by obi_create_column() or obi_clone_column(). + * @param line_nb The number of the line where the value should be recovered. + * @param element_name The name of the element that should be recovered in the line. + * + * @returns The recovered value. + * @retval '\0' the NA value of the type if an error occurred and obi_errno is set. + * + * @since February 2016 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +const char* obi_column_get_obiseq_with_elt_name_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name); + + #endif /* OBIDMSCOLUMN_SEQ_H_ */ diff --git a/src/obidmscolumn_str.c b/src/obidmscolumn_str.c index 72e332c..c92ca1d 100644 --- a/src/obidmscolumn_str.c +++ b/src/obidmscolumn_str.c @@ -14,6 +14,7 @@ #include #include "obidmscolumn.h" +#include "obiview.h" #include "obitypes.h" #include "obierrno.h" #include "obidebug.h" @@ -34,14 +35,6 @@ int obi_column_set_obistr_with_elt_idx(OBIDMS_column_p column, index_t line_nb, byte_t* value_b; index_t idx; - // Check that the column is not referring another - if ((column->header)->referring) - { - obi_set_errno(OBICOL_UNKNOWN_ERROR); - obidebug(1, "\nError: Setting a value from a referring column is not allowed. The referred column must be cloned to be modified"); - return -1; - } - // Check that the line number is not greater than the maximum allowed if (line_nb >= MAXIMUM_LINE_COUNT) { @@ -73,7 +66,7 @@ int obi_column_set_obistr_with_elt_idx(OBIDMS_column_p column, index_t line_nb, return -1; // Add the value's index in the column - *(((index_t*) (column->data)) + (line_nb * ((column->header)->stored_nb_elements_per_line)) + element_idx) = idx; + *(((index_t*) (column->data)) + (line_nb * ((column->header)->nb_elements_per_line)) + element_idx) = idx; free(value_b); @@ -81,44 +74,100 @@ int obi_column_set_obistr_with_elt_idx(OBIDMS_column_p column, index_t line_nb, } +int obi_column_set_obistr_with_elt_idx_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx, char* value) +{ + // Check that the view is not read-only + if (view->read_only) + { + obi_set_errno(OBIVIEW_ERROR); + obidebug(1, "\nError trying to set a value in a column in a read-only view"); + return -1; + } + + if ((view->line_selection != NULL) || (!(column->writable))) + { + // Get the right line number + if (column->writable) + line_nb = *(((index_t*) ((view->line_selection)->data)) + line_nb); + + column = obi_view_clone_column(view, (column->header)->name); + if (column == NULL) + { + obidebug(1, "\nError trying to clone a column to modify it"); + return -1; + } + } + + if ((line_nb+1) > view->line_count) + { + if (obi_view_update_lines(view, (line_nb+1)) < 0) + return -1; + } + + if (obi_column_set_obistr_with_elt_idx(column, line_nb, element_idx, value) < 0) + return -1; + + return 0; +} + + const char* obi_column_get_obistr_with_elt_idx(OBIDMS_column_p column, index_t line_nb, index_t element_idx) { index_t idx; byte_t* value_b; - index_t referring_idx; - if ((line_nb+1) > (column->header)->lines_used) + if ((line_nb+1) > ((column->header)->line_count)) { obi_set_errno(OBICOL_UNKNOWN_ERROR); - obidebug(1, "\nError trying to get a value that is beyond the current number of lines used"); - return "\0"; // TODO + obidebug(1, "\nError trying to get a value that is beyond the current number of lines used in the column"); + return OBIStr_NA; } - if ((column->header)->referring) - { - referring_idx = *(((index_t*) (column->data)) + line_nb); - idx = *(((index_t*) ((column->referred_column)->data)) + (referring_idx * ((column->header)->returned_nb_elements_per_line)) + element_idx); - } - else - idx = *(((index_t*) (column->data)) + (line_nb * ((column->header)->stored_nb_elements_per_line)) + element_idx); + idx = *(((index_t*) (column->data)) + (line_nb * ((column->header)->nb_elements_per_line)) + element_idx); // Check NA if (idx == OBIIdx_NA) - return "\0"; // TODO + return OBIStr_NA; value_b = obi_avl_get(column->avl, idx); return obi_obibytes_to_str(value_b); } +const char* obi_column_get_obistr_with_elt_idx_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx) +{ + if ((line_nb+1) > (view->line_count)) + { + obi_set_errno(OBICOL_UNKNOWN_ERROR); + obidebug(1, "\nError trying to get a value that is beyond the current line count of the view"); + return OBIStr_NA; + } + + if (view->line_selection) + line_nb = *(((index_t*) ((view->line_selection)->data)) + line_nb); + + return obi_column_get_obistr_with_elt_idx(column, line_nb, element_idx); +} + + int obi_column_set_obistr_with_elt_name(OBIDMS_column_p column, index_t line_nb, const char* element_name, char* value) { index_t element_idx; element_idx = obi_column_get_element_index_from_name(column, element_name); if (element_idx == OBIIdx_NA) return -1; - if (obi_column_set_obistr_with_elt_idx(column, line_nb, element_idx, value) < 0) + obi_column_set_obistr_with_elt_idx(column, line_nb, element_idx, value); + return 0; +} + + +int obi_column_set_obistr_with_elt_name_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name, char* value) +{ + index_t element_idx; + element_idx = obi_column_get_element_index_from_name(column, element_name); + if (element_idx == OBIIdx_NA) return -1; + obi_column_set_obistr_with_elt_idx_in_view(view, column, line_nb, element_idx, value); return 0; } @@ -129,7 +178,18 @@ const char* obi_column_get_obistr_with_elt_name(OBIDMS_column_p column, index_t element_idx = obi_column_get_element_index_from_name(column, element_name); if (element_idx == OBIIdx_NA) - return "\0"; + return OBIStr_NA; return obi_column_get_obistr_with_elt_idx(column, line_nb, element_idx); } + +const char* obi_column_get_obistr_with_elt_name_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name) +{ + index_t element_idx; + + element_idx = obi_column_get_element_index_from_name(column, element_name); + if (element_idx == OBIIdx_NA) + return OBIStr_NA; + return obi_column_get_obistr_with_elt_idx_in_view(view, column, line_nb, element_idx); +} + diff --git a/src/obidmscolumn_str.h b/src/obidmscolumn_str.h index 8bf7fdd..e511480 100644 --- a/src/obidmscolumn_str.h +++ b/src/obidmscolumn_str.h @@ -19,6 +19,7 @@ #include "obidmscolumn.h" #include "obitypes.h" +#include "obiview.h" /** @@ -97,5 +98,81 @@ int obi_column_set_obistr_with_elt_name(OBIDMS_column_p column, index_t line_nb, const char* obi_column_get_obistr_with_elt_name(OBIDMS_column_p column, index_t line_nb, const char* element_name); +/** + * @brief Sets a value in an OBIDMS column containing data in the form of indices referring + * to character strings in an AVL tree, using the index of the element in the line. + * + * @warning Pointers returned by obi_open_column() don't allow writing. + * + * @param column A pointer as returned by obi_create_column() or obi_clone_column(). + * @param line_nb The number of the line where the value should be set. + * @param element_idx The index of the element that should be set in the line. + * @param value The value that should be set. + * + * @returns An integer value indicating the success of the operation. + * @retval 0 on success. + * @retval -1 if an error occurred. + * + * @since February 2016 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +int obi_column_set_obistr_with_elt_idx_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx, char* value); + + +/** + * @brief Recovers a value in an OBIDMS column containing data in the form of indices referring + * to character strings in an AVL tree, using the index of the element in the line. + * + * @param column A pointer as returned by obi_create_column(). + * @param line_nb The number of the line where the value should be recovered. + * @param element_idx The index of the element that should be recovered in the line. + * + * @returns The recovered value. + * @retval '\0' the NA value of the type if an error occurred and obi_errno is set. + * + * @since February 2016 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +const char* obi_column_get_obistr_with_elt_idx_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx); + + +/** + * @brief Sets a value in an OBIDMS column containing data in the form of indices referring + * to character strings in an AVL tree, using the name of the element in the line. + * + * @warning Pointers returned by obi_open_column() don't allow writing. + * + * @param column A pointer as returned by obi_create_column() or obi_clone_column(). + * @param line_nb The number of the line where the value should be set. + * @param element_name The name of the element that should be set in the line. + * @param value The value that should be set. + * + * @returns An integer value indicating the success of the operation. + * @retval 0 on success. + * @retval -1 if an error occurred. + * + * @since February 2016 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +int obi_column_set_obistr_with_elt_name_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name, char* value); + + +/** + * @brief Recovers a value in an OBIDMS column containing data in the form of indices referring + * to character strings in an AVL tree, using the name of the element in the line. + * + * @param column A pointer as returned by obi_create_column() or obi_clone_column(). + * @param line_nb The number of the line where the value should be recovered. + * @param element_name The name of the element that should be recovered in the line. + * + * @returns The recovered value. + * @retval '\0' the NA value of the type if an error occurred and obi_errno is set. + * + * @since February 2016 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +const char* obi_column_get_obistr_with_elt_name_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, const char* element_name); + + #endif /* OBIDMSCOLUMN_STR_H_ */ diff --git a/src/obierrno.h b/src/obierrno.h index 5679f93..fd2da4f 100644 --- a/src/obierrno.h +++ b/src/obierrno.h @@ -100,6 +100,8 @@ extern int obi_errno; */ #define OBI_AVL_ERROR (20) /** Error while handling an AVL tree */ +#define OBIVIEW_ERROR (21) /** Error while handling an OBIView + */ /**@}*/ #endif /* OBIERRNO_H_ */ diff --git a/src/obitypes.h b/src/obitypes.h index 4f22cb9..8a70e90 100644 --- a/src/obitypes.h +++ b/src/obitypes.h @@ -23,6 +23,8 @@ #define OBIFloat_NA (float_NA()) /**< NA value for the type OBI_FLOAT */ #define OBIChar_NA (0) /**< NA value for the type OBI_CHAR */ // TODO not sure about this one as it can be impossible to distinguish from uninitialized values +#define OBISeq_NA ("\0") // TODO +#define OBIStr_NA ("\0") // TODO /** @@ -32,7 +34,7 @@ typedef enum OBIBool { FALSE = 0, TRUE = 1, OBIBool_NA = 2 -} obibool_t, *obibool_p; /**< a boolean true/false value */ +} obibool_t, *obibool_p; /**< a boolean true/false value */ // TODO check name convention? /** @@ -46,7 +48,7 @@ typedef enum OBIType { OBI_CHAR, /**< a character (C type : char) */ OBI_STR, /**< an index in a data structure (C type : int64_t) referring to a character string */ OBI_SEQ, /**< an index in a data structure (C type : int64_t) referring to a DNA sequence */ - OBI_IDX /**< an index referring to a line in another column (C type : int64_t) */ + OBI_IDX /**< an index referring to a line in another column (C type : int64_t) */ // TODO delete? } OBIType_t, *OBIType_p; diff --git a/src/obiview.c b/src/obiview.c new file mode 100644 index 0000000..f27670d --- /dev/null +++ b/src/obiview.c @@ -0,0 +1,949 @@ +/******************************************************************** + * Obiview functions * + ********************************************************************/ + +/** + * @file obiview.c + * @author Celine Mercier (celine.mercier@metabarcoding.org) + * @date 16 December 2015 + * @brief Obiview functions. + */ + + +// TODO +#include +#include +#include +#include +#include + +#include "obidms.h" +#include "obiview.h" +#include "obierrno.h" +#include "obidebug.h" +#include "obidmscolumn.h" +#include "private_at_functions.h" +#include "obilittlebigman.h" +#include "obidmscolumn_idx.h" + + +#define DEBUG_LEVEL 0 // TODO has to be defined somewhere else (cython compil flag?) + + +/************************************************************************** + * + * D E C L A R A T I O N O F T H E P R I V A T E F U N C T I O N S + * + **************************************************************************/ + + +/** + * Internal function building the file name where obiviews are stored. + * + * @warning The returned pointer has to be freed by the caller. + * + * @returns A pointer to the file name. + * @retval NULL if an error occurred. + * + * @param dms_name The name of the OBIDMS. + * + * @since December 2015 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +static char* build_obiview_file_name(); + + +/** TODO public + * Internal function creating the file containing basic informations on the OBIDMS. + * + * This file contains: + * - The endianness of the platform + * + * @warning The returned pointer has to be freed by the caller. + * + * @param dms_file_descriptor The file descriptor for the OBIDMS directory. + * @param dms_name The name of the OBIDMS. + * + * @retval 0 if the operation was successfully completed. + * @retval -1 if an error occurred. + * + * @since November 2015 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +int create_obiview_file(int dms_file_descriptor); + + +/************************************************************************ + * + * D E F I N I T I O N O F T H E P R I V A T E F U N C T I O N S + * + ************************************************************************/ + +static char* build_obiview_file_name() +{ + char* file_name; + + // Build file name + if (asprintf(&file_name, OBIVIEW_FILE_NAME) < 0) + { + obi_set_errno(OBIVIEW_ERROR); + obidebug(1, "\nProblem building an obiview file name"); + return NULL; + } + + return file_name; +} + + +size_t get_platform_header_size() +{ + size_t header_size; + size_t rounded_header_size; + double multiple; + + header_size = sizeof(Obiviews_header_t); + + multiple = ceil((double) header_size / (double) getpagesize()); + + rounded_header_size = multiple * getpagesize(); + + return rounded_header_size; +} + + +size_t get_platform_views_size(nb_of_views) +{ + size_t obiview_size; + size_t rounded_obiview_size; + double multiple; + + obiview_size = sizeof(Obiview_infos_t); + + multiple = ceil((double) (obiview_size*nb_of_views) / (double) getpagesize()); + + rounded_obiview_size = multiple * getpagesize(); + + return rounded_obiview_size; +} + + +int create_obiview_file(int dms_file_descriptor) +{ + char* file_name; + int obiview_file_descriptor; + size_t header_size; +// size_t view_size; + size_t file_size; + Obiviews_header_p header; + + // Create file name + file_name = build_obiview_file_name(); + if (file_name == NULL) + return -1; + + // Create file + obiview_file_descriptor = openat(dms_file_descriptor, file_name, O_RDWR | O_CREAT | O_EXCL, 0777); + if (obiview_file_descriptor < 0) + { + obi_set_errno(OBIVIEW_ERROR); + obidebug(1, "\nError creating an obiview file"); + free(file_name); + return -1; + } + + free(file_name); + + // Truncate file to the right size + header_size = get_platform_header_size(); + //view_size = get_platform_views_size(1); + file_size = header_size; // + view_size; + + if (ftruncate(obiview_file_descriptor, file_size) < 0) + { + obi_set_errno(OBIVIEW_ERROR); + obidebug(1, "\nError truncating an obiview file to the right size"); + close(obiview_file_descriptor); + return -1; + } + + // Map the header + header = mmap(NULL, + header_size, + PROT_READ | PROT_WRITE, + MAP_SHARED, + obiview_file_descriptor, + 0 + ); + if (header == MAP_FAILED) + { + obi_set_errno(OBIVIEW_ERROR); + obidebug(1, "\nError mmapping an obiview file header"); + close(obiview_file_descriptor); + return -1; + } + + // Initialize the header + header->header_size = header_size; + header->views_size = 0; + header->view_count = 0; + + // Unmap the header + if (munmap(header, header_size) < 0) + { + obi_set_errno(OBIVIEW_ERROR); + obidebug(1, "\nError munmapping an obiview file header"); + close(obiview_file_descriptor); + return -1; + } + + close(obiview_file_descriptor); + + return 0; +} + + +/********************************************************************** + * + * D E F I N I T I O N O F T H E P U B L I C F U N C T I O N S + * + **********************************************************************/ + + +Obiview_p obi_new_view(OBIDMS_p dms, const char* view_name, Obiview_p view_to_clone, index_t* line_selection) +{ + Obiview_p view; + int i; + index_t line_nb; + + view = (Obiview_p) malloc(sizeof(Obiview_t)); + if (view == NULL) + { + obi_set_errno(OBIVIEW_ERROR); + obidebug(1, "\nError allocating memory for a view"); + return NULL; + } + + // Clone view to clone if there is one + if (view_to_clone != NULL) + { + if (!(view_to_clone->read_only)) + { + obi_set_errno(OBIVIEW_ERROR); + obidebug(1, "\nA view can not be cloned if it is not read-only"); + free(view); + return NULL; + } + + view->dms = dms; + view->column_count = view_to_clone->column_count; + if ((view_to_clone->line_selection != NULL) && (line_selection == NULL)) // reorder conditions + { + view->line_selection = obi_open_column(dms, ((view_to_clone->line_selection)->header)->name, ((view_to_clone->line_selection)->header)->version); + if (view->line_selection == NULL) + return NULL; + view->line_count = view_to_clone->line_count; + } + else if (line_selection != NULL) + { + view->line_selection = obi_create_column(view->dms, LINES_COLUMN_NAME, OBI_IDX, 0, 1, LINES_COLUMN_NAME, NULL, NULL); + if ((view->line_selection) == NULL) + { + obidebug(1, "\nError creating a column corresponding to a line selection"); + return NULL; + } + view->line_count = 0; + i = 0; + for (i=0; line_selection[i] != -1; i++) + { + line_nb = line_selection[i]; + + if (line_nb > view_to_clone->line_count) + { + obi_set_errno(OBIVIEW_ERROR); + obidebug(1, "\nError trying to select a line for a new view that is beyond the line count of the view to clone"); + obi_close_column(view->line_selection); + free(view); + return NULL; + } + + if (view_to_clone->line_selection != NULL) + line_nb = obi_column_get_index(view_to_clone->line_selection, line_nb); + + if (obi_column_set_index(view->line_selection, ((view->line_selection)->header)->lines_used, line_nb) < 0) + { + obi_close_column(view->line_selection); + free(view); + return NULL; + } + + // Update view line count + (view->line_count)++; + } + } + else + { + view->line_selection = NULL; + view->line_count = view_to_clone->line_count; + } + + for (i=0; i<(view_to_clone->column_count); i++) + { + (view->columns)[i] = obi_open_column(dms, (((view_to_clone->columns)[i])->header)->name, (((view_to_clone->columns)[i])->header)->version); + if ((view->columns)[i] == NULL) + { + obi_close_column(view->line_selection); + free(view); + return NULL; + } + } + + strcpy(view->created_from, view_to_clone->name); + view->new_line_selection = NULL; + } + // Else, fill empty view structure + else + { + view->dms = dms; + view->column_count = 0; + view->line_count = 0; + view->line_selection = NULL; + view->new_line_selection = NULL; + (view->created_from)[0] = '\0'; + //view->columns = NULL; TODO + } + + strcpy(view->name, view_name); + view->read_only = 0; + + return view; +} + + +Obiview_p obi_new_view_cloned_from_name(OBIDMS_p dms, const char* view_name, const char* view_to_clone_name, index_t* line_selection) +{ + Obiview_p view; + Obiview_p view_to_clone; + + view_to_clone = obi_open_view(dms, view_to_clone_name); + if (view_to_clone == NULL) + return NULL; + view = obi_new_view(dms, view_name, view_to_clone, line_selection); + return view; +} + + +Obiview_p obi_open_view(OBIDMS_p dms, const char* view_name) +{ + Obiview_p view; + bool first_view; + char* view_file_name; + int obiview_file_descriptor; + size_t header_size; + Obiviews_header_p header; + Obiview_infos_p views; + Obiview_infos_p view_infos; + OBIDMS_column_p column; + int i; + int view_number; + + // Check if 1st view : view file doesn't exist + first_view = 0; + + view_file_name = build_obiview_file_name(); + if (view_file_name == NULL) + return NULL; + + // Open view file, read header size and map header and views + obiview_file_descriptor = openat(dms->dir_fd, view_file_name, O_RDWR, 0777); + if (obiview_file_descriptor < 0) + { + obi_set_errno(OBIVIEW_ERROR); + obidebug(1, "\nError opening an obiview file"); + free(view_file_name); + return NULL; + } + + free(view_file_name); + + // Read the header size + if (read(obiview_file_descriptor, &header_size, sizeof(size_t)) < ((ssize_t) sizeof(size_t))) + { + obi_set_errno(OBIVIEW_ERROR); + obidebug(1, "\nError reading the header size of an obiview file (trying to open a view when there are none?)"); + close(obiview_file_descriptor); + return NULL; + } + + // Map the header + header = mmap(NULL, + header_size, + PROT_READ | PROT_WRITE, + MAP_SHARED, + obiview_file_descriptor, + 0 + ); + if (header == MAP_FAILED) + { + obi_set_errno(OBIVIEW_ERROR); + obidebug(1, "\nError mmapping an obiview file header"); + close(obiview_file_descriptor); + return NULL; + } + + // Map the views + views = mmap(NULL, + header->views_size, + PROT_READ | PROT_WRITE, + MAP_SHARED, + obiview_file_descriptor, + header_size + ); + if (views == MAP_FAILED) + { + obi_set_errno(OBIVIEW_ERROR); + obidebug(1, "\nError mmapping the views from an obiview file"); + munmap(header, header_size); + close(obiview_file_descriptor); + return NULL; + } + + // Find and open view that should be read with the line selection associated + view_number = -1; + if (view_name == NULL) // If view name is NULL, open the latest view TODO discuss + view_number = (header->view_count) - 1; + else + { + for (i=0; i<(header->view_count); i++) + { + if (!strcmp((views+i)->name, view_name)) + { // Found the view to open + view_number = i; + } + } + } + + if (view_number == -1) + { + obi_set_errno(OBIVIEW_ERROR); + obidebug(1, "\nError: the view '%s' to open was not found", view_name); + munmap(views, header->views_size); + munmap(header, header_size); + close(obiview_file_descriptor); + return NULL; + } + + view_infos = views + view_number; + + view = (Obiview_p) malloc(sizeof(Obiview_t)); + if (view == NULL) + { + obi_set_errno(OBIVIEW_ERROR); + obidebug(1, "\nError allocating memory for a view"); + munmap(views, header->views_size); + munmap(header, header_size); + close(obiview_file_descriptor); + return NULL; + } + + if (view_infos->all_lines) + view->line_selection = NULL; + else + { + view->line_selection = obi_open_column(dms, (view_infos->line_selection).column_name, (view_infos->line_selection).version); + if (view->line_selection == NULL) + { + munmap(views, header->views_size); + munmap(header, header_size); + close(obiview_file_descriptor); + return NULL; + } + } + + view->dms = dms; + view->new_line_selection = NULL; + view->read_only = 1; + view->column_count = 0; + view->line_count = view_infos->line_count; + strcpy(view->created_from, view_infos->created_from); + strcpy(view->name, view_infos->name); + + // Open the columns to read + for (i=0; i<(view_infos->column_count); i++) + { + column = obi_open_column(dms, ((view_infos->column_references)+i)->column_name, ((view_infos->column_references)+i)->version); + if (column == NULL) + { + obidebug(1, "\nError opening a column for a view: column %d: %s, version %d", i, ((view_infos->column_references)+i)->column_name, ((view_infos->column_references)+i)->version); + munmap(views, header->views_size); + munmap(header, header_size); + close(obiview_file_descriptor); + return NULL; + } + // Store column in the view + (view->columns)[view->column_count] = column; + view->column_count++; + } + + // Munmap and close things TODO + munmap(views, header->views_size); + munmap(header, header_size); + close(obiview_file_descriptor); + + return view; +} + + +int obi_view_add_column(Obiview_p view, + const char* column_name, + obiversion_t version_number, + OBIType_t data_type, + index_t nb_lines, + index_t nb_elements_per_line, + const char* elements_names, + const char* avl_name, + const char* comments, + bool create) // all infos for creation or open +{ + OBIDMS_column_p column; + + // Check that the view is not read-only + if (view->read_only) + { + obi_set_errno(OBIVIEW_ERROR); + obidebug(1, "\nError trying to add a column in a read-only view"); + return -1; + } + + if (view->line_count > nb_lines) + nb_lines = view->line_count; + else if (nb_lines > view->line_count) + obi_view_update_lines(view, nb_lines); + + // Open or create the column + if (create) + { // Create column + column = obi_create_column(view->dms, column_name, data_type, nb_lines, nb_elements_per_line, elements_names, avl_name, comments); + } + else + { // Open column + column = obi_open_column(view->dms, column_name, version_number); + } + + if (column == NULL) + { + obidebug(1, "\nError creating or opening a column to add to a view"); + return -1; + } + + // Store column in the view + (view->columns)[view->column_count] = column; + view->column_count++; + if (view->column_count == 1) // first column in the view + view->line_count = (column->header)->lines_used; + + return 0; +} + + +OBIDMS_column_p obi_view_clone_column(Obiview_p view, const char* column_name) +{ + int i; + OBIDMS_column_p current_line_selection = NULL; + OBIDMS_column_p column; + OBIDMS_column_p column_buffer; + + // Check that the view is not read-only + if (view->read_only) + { + obi_set_errno(OBIVIEW_ERROR); + obidebug(1, "\nError trying to delete a column in a read-only view"); + return NULL; + } + + if (view->new_line_selection != NULL) // TODO Probably shouldn't happen + current_line_selection = view->new_line_selection; + else + current_line_selection = view->line_selection; + + for (i=0; i<(view->column_count); i++) + { + if ((current_line_selection != NULL) || (!(strcmp((((view->columns)[i])->header)->name, column_name)))) + { // Clone with the right line selection and replace + column_buffer = (view->columns)[i]; + (view->columns)[i] = obi_clone_column(view->dms, current_line_selection, (((view->columns)[i])->header)->name, (((view->columns)[i])->header)->version, 1); + if ((view->columns)[i] == NULL) + { + obi_set_errno(OBIVIEW_ERROR); + obidebug(1, "\nError cloning a column to replace in a view"); + return NULL; + } + // Found the column to return + if (!(strcmp((((view->columns)[i])->header)->name, column_name))) + column = (view->columns)[i]; + else + obi_truncate_and_close_column(column_buffer); // TODO weird closing after cloning but can't think of cleaner yet + } + } + + if (view->line_selection != NULL) + { + obi_truncate_and_close_column(view->line_selection); + view->line_selection = NULL; + } + if (view->new_line_selection != NULL) + { + obi_truncate_and_close_column(view->new_line_selection); + view->new_line_selection = NULL; + } + + return column; +} + + +int obi_view_delete_column(Obiview_p view, const char* column_name) +{ + int i; + bool found; + + // Check that the view is not read-only + if (view->read_only) + { + obi_set_errno(OBIVIEW_ERROR); + obidebug(1, "\nError trying to delete a column in a read-only view"); + return -1; + } + + found = 0; + + for (i=0; i<(view->column_count); i++) + { + if (!strcmp((((view->columns)[i])->header)->name, column_name)) + { + obi_truncate_and_close_column((view->columns)[i]); + found = 1; + } + if (found) + { + if (i != ((view->column_count) - 1)) // not the last one + (view->columns)[i] = (view->columns)[i+1]; + else // Last column + (view->columns)[i] = NULL; + } + } + + if (!found) + return -1; + + (view->column_count)--; + + return 0; +} + + +int obi_select_line(Obiview_p view, index_t line_nb) +{ + // Check that the view is not read-only + if (view->read_only) + { + obi_set_errno(OBIVIEW_ERROR); + obidebug(1, "\nError trying to select a line in a read-only view"); + return -1; + } + + // If column for line selection doesn't already exists, create it and store its informations + if ((view->new_line_selection) == NULL) + { + view->new_line_selection = obi_create_column(view->dms, LINES_COLUMN_NAME, OBI_IDX, 0, 1, LINES_COLUMN_NAME, NULL, NULL); + if ((view->new_line_selection) == NULL) + { + obidebug(1, "\nError creating a column corresponding to a line selection"); + return -1; + } + } + + // If we are already working on a line selection, get the pointed line number + if (view->line_selection) + line_nb = obi_column_get_index(view->line_selection, line_nb); + + if (obi_column_set_index(view->new_line_selection, ((view->new_line_selection)->header)->lines_used, line_nb) < 0) + return -1; + + return 0; +} + + +int obi_select_lines(Obiview_p view, index_t* line_nbs) +{ + int i; + index_t line_nb; + + // Check that the view is not read-only + if (view->read_only) + { + obi_set_errno(OBIVIEW_ERROR); + obidebug(1, "\nError trying to select a line in a read-only view"); + return -1; + } + + // If column for line selection doesn't already exists, create it and store its informations + if ((view->new_line_selection) == NULL) + { + view->new_line_selection = obi_create_column(view->dms, LINES_COLUMN_NAME, OBI_IDX, 0, 1, LINES_COLUMN_NAME, NULL, NULL); + if ((view->new_line_selection) == NULL) + { + obidebug(1, "\nError creating a column corresponding to a line selection"); + return -1; + } + } + + for (i=0; line_nbs[i] != -1; i++) + { + line_nb = line_nbs[i]; + + // If we are already working on a line selection, get the pointed line number + if (view->line_selection) + line_nb = obi_column_get_index(view->line_selection, line_nb); + + if (obi_column_set_index(view->new_line_selection, ((view->new_line_selection)->header)->lines_used, line_nb) < 0) + return -1; + } + + return 0; +} + + +int obi_view_update_lines(Obiview_p view, index_t line_count) +{ + int i; + + for (i=0; i<(view->column_count); i++) + { + while (line_count > (((view->columns)[i])->header)->line_count) + { + // Enlarge the column + if (obi_enlarge_column((view->columns)[i]) < 0) + return -1; + } + } + + view->line_count = line_count; + + return 0; +} + + +OBIDMS_column_p obi_view_get_column(Obiview_p view, const char* column_name) +{ + int i; + + for (i=0; i<(view->column_count); i++) + { + if (!(strcmp((((view->columns)[i])->header)->name, column_name))) + return (view->columns)[i]; + } + return NULL; +} + + +OBIDMS_column_p* obi_view_get_pointer_on_column_in_view(Obiview_p view, const char* column_name) +{ + int i; + + for (i=0; i<(view->column_count); i++) + { + if (!(strcmp((((view->columns)[i])->header)->name, column_name))) + return ((view->columns)+i); + } + return NULL; +} + + +int obi_save_view(Obiview_p view) +{ + int i; + struct stat buffer; + char* view_file_name; + char* full_path; + int check_file; + int obiview_file_descriptor; + size_t header_size; + size_t views_size; + size_t file_size; + Obiviews_header_p header; + Obiview_infos_p views; + Obiview_infos_p view_infos; + OBIDMS_column_p current_line_selection; + + // Check that the view is not read-only + if (view->read_only) + { + obi_set_errno(OBIVIEW_ERROR); + obidebug(1, "\nError trying to save a read-only view"); + return -1; + } + + view_file_name = build_obiview_file_name(); + if (view_file_name == NULL) + return -1; + + // Get the full path for the column directory + full_path = get_full_path((view->dms)->dir_fd, view_file_name); + if (full_path == NULL) + { + obi_set_errno(OBIVIEW_ERROR); + obidebug(1, "\nError getting the full path of an obiview file"); + free(view_file_name); + return -1; + } + + check_file = stat(full_path, &buffer); + if (check_file < 0) + { // 1st view: create view file + if (create_obiview_file((view->dms)->dir_fd) < 0) + return -1; + } + + // Open view file, read header size and map header and views + obiview_file_descriptor = openat((view->dms)->dir_fd, view_file_name, O_RDWR, 0777); + if (obiview_file_descriptor < 0) + { + obi_set_errno(OBIVIEW_ERROR); + obidebug(1, "\nError opening an obiview file"); + free(view_file_name); + return -1; + } + + free(view_file_name); + + // Read the header size + if (read(obiview_file_descriptor, &header_size, sizeof(size_t)) < ((ssize_t) sizeof(size_t))) + { + obi_set_errno(OBIVIEW_ERROR); + obidebug(1, "\nError reading the header size of an obiview file"); + close(obiview_file_descriptor); + return -1; + } + + // Map the header + header = mmap(NULL, + header_size, + PROT_READ | PROT_WRITE, + MAP_SHARED, + obiview_file_descriptor, + 0 + ); + if (header == MAP_FAILED) + { + obi_set_errno(OBIVIEW_ERROR); + obidebug(1, "\nError mmapping an obiview file header"); + close(obiview_file_descriptor); + return -1; + } + + // Truncate file to the right size to add a new view // TODO lock for multithreading + views_size = get_platform_views_size((header->view_count)+1); + file_size = header_size + views_size; + + if (ftruncate(obiview_file_descriptor, file_size) < 0) + { + obi_set_errno(OBIVIEW_ERROR); + obidebug(1, "\nError truncating an obiview file to the right size"); + munmap(header, header_size); + close(obiview_file_descriptor); + return -1; + } + + header->views_size = views_size; + + // Map the views + views = mmap(NULL, + header->views_size, + PROT_READ | PROT_WRITE, + MAP_SHARED, + obiview_file_descriptor, + header_size + ); + if (views == MAP_FAILED) + { + obi_set_errno(OBIVIEW_ERROR); + obidebug(1, "\nError mmapping the views from an obiview file"); + munmap(header, header_size); + close(obiview_file_descriptor); + return -1; + } + + // Write view infos + view_infos = views + (header->view_count); + view_infos->view_number = (header->view_count); + view_infos->column_count = view->column_count; + view_infos->creation_date = time(NULL); + strcpy(view_infos->created_from, view->created_from); + strcpy(view_infos->name, view->name); + // Store reference for the line selection associated with that view + if (view->new_line_selection != NULL) + { + view_infos->line_count = ((view->new_line_selection)->header)->lines_used; + current_line_selection = view->new_line_selection; + } + else + { + view_infos->line_count = view->line_count; + current_line_selection = view->line_selection; + } + if (current_line_selection != NULL) + { + view_infos->all_lines = 0; + strcpy((view_infos->line_selection).column_name, (current_line_selection->header)->name); + (view_infos->line_selection).version = (current_line_selection->header)->version; + } + else + { + view_infos->all_lines = 1; + ((view_infos->line_selection).column_name)[0] = '\0'; + (view_infos->line_selection).version = -1; + } + for (i=0; icolumn_count; i++) + { + strcpy(((view_infos->column_references)+i)->column_name, (((view->columns)[i])->header)->name); + ((view_infos->column_references)+i)->version = (((view->columns)[i])->header)->version; + } + + // Increment view count + (header->view_count)++; + + // Unmap and close file + munmap(views, header->views_size); + munmap(header, header_size); + close(obiview_file_descriptor); + + return 0; +} + + +int obi_close_view(Obiview_p view) +{ + int i; + + for (i=0; i < (view->column_count); i++) + { + obi_close_column((view->columns)[i]); + } + + free(view); + + return 0; +} + + +int obi_save_and_close_view(Obiview_p view) +{ + if (!(view->read_only)) // TODO discuss + { + if (obi_save_view(view) < 0) + return -1; + } + if (obi_close_view(view) < 0) + return -1; + return 0; +} + diff --git a/src/obiview.h b/src/obiview.h new file mode 100644 index 0000000..d006ef3 --- /dev/null +++ b/src/obiview.h @@ -0,0 +1,158 @@ +/******************************************************************** + * Obiview header file * + ********************************************************************/ + +/** + * @file obiview.h + * @author Celine Mercier (celine.mercier@metabarcoding.org) + * @date 16 December 2015 + * @brief Header file for the OBIDMS view functions and structures. + */ + + +#ifndef OBIVIEW_H_ +#define OBIVIEW_H_ + + +#include +#include +#include +#include +#include +#include + +#include "obidms.h" +#include "obidmscolumn.h" +#include "obierrno.h" + + +#define OBIVIEW_NAME_MAX_LENGTH (10239) /**< The maximum length of an OBIDMS view name. + */ +#define OBIVIEW_FILE_NAME "obiviews" + +#define LINES_COLUMN_NAME "LINES" + + +/** + * @brief . + */ +typedef struct Column_reference { + char column_name[OBIDMS_COLUMN_MAX_NAME+1]; /**< Name of the column. + */ + obiversion_t version; /**< Version of the column. + */ +} Column_reference_t, *Column_reference_p; + + +/** + * @brief . + */ +typedef struct Obiview { + + OBIDMS_p dms; + + bool read_only; + + OBIDMS_column_p line_selection; + + OBIDMS_column_p new_line_selection; + + index_t line_count; + + int column_count; + + OBIDMS_column_p columns[MAX_NB_OPENED_COLUMNS]; + + char name[OBIVIEW_NAME_MAX_LENGTH+1]; + + char created_from[OBIVIEW_NAME_MAX_LENGTH+1]; + + int view_number; + +} Obiview_t, *Obiview_p; + + +/** + * @brief . + */ +typedef struct Obiview_infos { + int view_number; + + int column_count; + + index_t line_count; + + char name[OBIVIEW_NAME_MAX_LENGTH+1]; + + char created_from[OBIVIEW_NAME_MAX_LENGTH+1]; + + time_t creation_date; + + bool all_lines; + + Column_reference_t line_selection; + + Column_reference_t column_references[MAX_NB_OPENED_COLUMNS]; + +} Obiview_infos_t, *Obiview_infos_p; + + +/** + * @brief . + */ +typedef struct Obiviews_header { + size_t header_size; + size_t views_size; + int view_count; +} Obiviews_header_t, *Obiviews_header_p; + + +/** + * @brief . + */ +typedef struct Obiviews { // not used + Obiviews_header_p header; + + Obiview_infos_p views; + +} Obiviews_t, *Obiviews_p; + + +Obiview_p obi_new_view(OBIDMS_p dms, const char* view_name, Obiview_p view_to_clone, index_t* line_selection); + +Obiview_p obi_new_view_cloned_from_name(OBIDMS_p dms, const char* view_name, const char* view_to_clone_name, index_t* line_selection); + +Obiview_p obi_open_view(OBIDMS_p dms, const char* view_name); + +int obi_view_add_column(Obiview_p view, + const char* column_name, + obiversion_t version_number, + OBIType_t data_type, + index_t nb_lines, + index_t nb_elements_per_line, + const char* elements_names, + const char* avl_name, + const char* comments, + bool create); + +int obi_view_delete_column(Obiview_p view, const char* column_name); + +int obi_select_line(Obiview_p view, index_t line_nb); + +int obi_select_lines(Obiview_p view, index_t* line_nbs); + +int obi_view_update_lines(Obiview_p view, index_t line_count); + +OBIDMS_column_p obi_view_clone_column(Obiview_p view, const char* column_name); + +OBIDMS_column_p obi_view_get_column(Obiview_p view, const char* column_name); + +OBIDMS_column_p* obi_view_get_pointer_on_column_in_view(Obiview_p view, const char* column_name); + +int obi_save_view(Obiview_p view); + +int obi_close_view(Obiview_p view); + +int obi_save_and_close_view(Obiview_p view); + +#endif /* OBIVIEW_H_ */