/* * events.c * * Event properties * * Copyright © 2012-2020 Deutsches Elektronen-Synchrotron DESY, * a research centre of the Helmholtz Association. * * Authors: * 2017 Thomas White * 2014 Valerio Mariani * * This file is part of CrystFEL. * * CrystFEL is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CrystFEL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with CrystFEL. If not, see . * */ #include "events.h" #include "utils.h" #include #include #include #include /** \file events.h */ struct event *initialize_event() { struct event *ev; ev = malloc(sizeof(struct event)); ev->path_entries = NULL; ev->path_length = 0; ev->dim_entries = NULL; ev->dim_length = 0; return ev; } struct event_list *initialize_event_list() { struct event_list *ev_list; ev_list = malloc(sizeof(struct event_list)); ev_list->events = NULL; ev_list->num_events = 0; return ev_list; } struct filename_plus_event *initialize_filename_plus_event() { struct filename_plus_event *fpe; fpe = malloc(sizeof(struct filename_plus_event)); fpe->filename = NULL; fpe->ev = NULL; return fpe; } int event_cmp(struct event *ev1, struct event *ev2) { int pi; int di; if ( ev1->path_length != ev2->path_length || ev1->dim_length != ev2->dim_length ) { return 1; } for ( pi=0; pipath_length; pi++ ) { if ( strcmp(ev1->path_entries[pi], ev2->path_entries[pi]) != 0 ) { return 1; } } for ( di=0; didim_length; di++ ) { if ( ev1->path_entries[di] != ev2->path_entries[di] ) { return 1; } } return 0; } int add_non_existing_event_to_event_list(struct event_list *ev_list, struct event *ev) { int evi; int found = 0; for ( evi=0; evinum_events; evi++ ) { if (event_cmp(ev_list->events[evi], ev) == 0 ) { found = 1; break; } } if ( found == 0) { return append_event_to_event_list(ev_list, ev); } return 0; } int append_event_to_event_list(struct event_list *ev_list, struct event *ev) { struct event **new_el; new_el = realloc(ev_list->events, (1+ev_list->num_events)*sizeof(struct event*)); if ( new_el == NULL ) return 1; ev_list->events = new_el; ev_list->events[ev_list->num_events] = copy_event(ev); ev_list->num_events +=1; return 0; } struct event *copy_event(struct event *ev) { struct event *new_ev; int pi, di; if ( ev == NULL ) return NULL; if ( ev->dim_length == 0 && ev->path_length == 0) { new_ev = initialize_event(); } else { new_ev=malloc(sizeof(struct event)); new_ev->path_entries = malloc(ev->path_length*sizeof(char *)); new_ev->path_length = ev->path_length; new_ev->dim_entries = malloc(ev->dim_length*sizeof(int *)); new_ev->dim_length = ev->dim_length; for ( pi=0; pipath_length; pi++ ) { new_ev->path_entries[pi] = strdup(ev->path_entries[pi]); } for ( di=0; didim_length; di++ ) { new_ev->dim_entries[di] = ev->dim_entries[di]; } } return new_ev; } struct event_list *copy_event_list(struct event_list *el) { int ei; struct event_list *el_copy; struct event **events_copy; el_copy = malloc(1); if ( el_copy == NULL ) { return NULL; } events_copy = malloc(el->num_events); if ( events_copy == NULL ) { free (el_copy); return NULL; } el_copy->events = events_copy; for ( ei=0; einum_events; ei++ ) { el_copy->events[ei]=copy_event(el->events[ei]); } el_copy->num_events = el->num_events; return el_copy; } static int events_equal(struct event *ev1, struct event *ev2) { int i; if ( ev1->path_length != ev2->path_length ) return 0; if ( ev1->dim_length != ev2->dim_length ) return 0; for ( i=0; ipath_length; i++ ) { if ( strcmp(ev1->path_entries[i], ev2->path_entries[i]) != 0 ) { return 0; } } for ( i=0; idim_length; i++ ) { if ( ev1->dim_entries[i] != ev2->dim_entries[i] ) return 0; } return 1; } /** * \param ev: An event structure * \param el: An event list * * \returns The indexing into \p el of the event matching \p ev, of el->num_events * if no such event is found. **/ int find_event(struct event *ev, struct event_list *el) { int i; if ( ev == NULL ) return el->num_events; for ( i=0; inum_events; i++ ) { if ( events_equal(ev, el->events[i]) ) return i; } return i; } void free_event(struct event *ev) { int pi; if ( ev == NULL ) return; if ( ev->path_length != 0 ) { for ( pi=0; pipath_length; pi++ ) { free(ev->path_entries[pi]); } } free(ev->dim_entries); free(ev); } void free_event_list(struct event_list *el) { int ei; for ( ei=0; einum_events; ei++ ) { free_event(el->events[ei]); } free(el); } void free_filename_plus_event(struct filename_plus_event *fpe) { free(fpe->filename); if ( fpe->ev != NULL ) { free_event(fpe->ev); } free(fpe); } char *get_event_string(struct event *ev) { char *evstr; int i; size_t ev_len; if ( ev == NULL ) return strdup("(none)"); ev_len = 1; /* Zero terminator */ for ( i=0; ipath_length; i++ ) { ev_len += strlen(ev->path_entries[i]); ev_len += 1; /* Slash afterwards */ } ev_len += 16*ev->dim_length; /* Max length of number plus slash */ ev_len += 2; /* Double slash in middle */ evstr = malloc(ev_len); if ( evstr == NULL ) return NULL; evstr[0] = '\0'; for ( i=0; ipath_length; i++ ) { if ( i > 0 ) strcat(evstr, "/"); strcat(evstr, ev->path_entries[i]); } strcat(evstr, "//"); for ( i=0; idim_length; i++ ) { char num_buf[16]; snprintf(num_buf, 16, "%i", ev->dim_entries[i]); if ( i > 0 ) strcat(evstr, "/"); strcat(evstr, num_buf); } return evstr; } struct event *get_event_from_event_string(const char *ev_string) { struct event *ev; char *ev_sep; char buf_path[1024]; char buf_dim[1024]; char *sep; char *start; ev_sep = strstr(ev_string, "//"); if ( ev_sep == NULL ) return NULL; strncpy(buf_path, ev_string, ev_sep-ev_string); buf_path[ev_sep-ev_string] = '\0'; strncpy(buf_dim, ev_sep+2, strlen(ev_sep)-2); buf_dim[strlen(ev_sep)-2] = '\0'; ev = initialize_event(); if ( ev == NULL ) return NULL; if ( strlen(buf_path) !=0 ) { start = buf_path; do { char buf[2014]; sep = strstr(start, "/"); if ( sep != NULL ) { strncpy(buf, start, sep-start); buf[sep-start]='\0'; push_path_entry_to_event(ev, buf); start = sep + 1; } else { sprintf(buf,"%s",start); push_path_entry_to_event(ev, buf); } } while (sep); } if ( strlen(buf_dim) !=0 ) { start = buf_dim; do { char buf[2014]; int buf_int; sep = strstr(start, "/"); if ( sep != NULL ) { strncpy(buf, start, sep-start); buf[sep-start]='\0'; buf_int = atoi(buf); push_dim_entry_to_event(ev, buf_int); start = sep + 1; } else { sprintf(buf,"%s",start); buf_int = atoi(buf); push_dim_entry_to_event(ev, buf_int); } } while (sep); } return ev; } int push_path_entry_to_event(struct event *ev, const char *entry) { char **new_path_entries; new_path_entries = realloc(ev->path_entries, (1+ev->path_length)*sizeof(char *)); if ( new_path_entries == NULL ) return 1; ev->path_entries = new_path_entries; ev->path_entries[ev->path_length] = strdup(entry); ev->path_length += 1; return 0; } int push_dim_entry_to_event(struct event *ev, int entry) { int *new_dim_entries; new_dim_entries = realloc(ev->dim_entries, (1+ev->dim_length)*sizeof(int)); if ( new_dim_entries == NULL ) return 1; ev->dim_entries = new_dim_entries; ev->dim_entries[ev->dim_length] = entry; ev->dim_length += 1; return 0; } int pop_path_entry_from_event(struct event *ev) { char **new_path_entries; if ( ev->path_length == 0 ) return 1; free(ev->path_entries[ev->path_length-1]); if ( ev->path_length == 1 ) { ev->path_entries = NULL; ev->path_length = 0; return 0; } new_path_entries = realloc(ev->path_entries, (ev->path_length-1)*sizeof(char *)); if ( new_path_entries == NULL ) return 1; ev->path_entries = new_path_entries; ev->path_length = ev->path_length-1; return 0; } int pop_dim_entry_from_event(struct event *ev) { int *new_dim_entries; if ( ev->dim_length == 0 ) { return 1; } if ( ev->dim_length == 1 ) { ev->dim_entries = NULL; ev->dim_length = 0; return 0; } new_dim_entries = realloc(ev->dim_entries, (ev->dim_length-1)*sizeof(int)); if ( new_dim_entries == NULL) { return 1; } ev->dim_entries = new_dim_entries; ev->dim_length = ev->dim_length-1; return 0; } char *event_path_placeholder_subst(const char *entry, const char *data) { char *ph_loc; char *full_path; ptrdiff_t len_head; size_t len_entry, len_data; len_entry = strlen(entry); len_data = strlen(data); full_path = malloc(len_data + len_entry + 1); if ( full_path == NULL ) return NULL; ph_loc = strchr(data, '%'); len_head = ph_loc - data; assert(len_head >= 0); strncpy(full_path, data, len_head); full_path[len_head] = '\0'; strcat(full_path, entry); strcat(full_path, ph_loc+1); return full_path; } char *retrieve_full_path(struct event *ev, const char *data) { int ei ; char *return_value; char *pholder; return_value = strdup(data); pholder = strstr(return_value,"%"); ei = 0; while ( pholder != NULL ) { char *tmp; /* Check we have enough things to put in the placeholders */ if ( ei >= ev->path_length ) { ERROR("Too many placeholders ('%%') in location.\n"); return NULL; } /* Substitute one placeholder */ tmp = event_path_placeholder_subst(ev->path_entries[ei++], return_value); if ( tmp == NULL ) { ERROR("Couldn't substitute placeholder\n"); return NULL; } /* Next time, we will substitute the next part of the path into * the partially substituted string */ free(return_value); return_value = tmp; pholder = strstr(return_value, "%"); } return return_value; } struct dim_structure *initialize_dim_structure() { struct dim_structure *hs; hs = malloc(sizeof(struct dim_structure)); if ( hs == NULL ) return NULL; hs->dims = NULL; hs->num_dims = 0; return hs; } struct dim_structure *default_dim_structure() { struct dim_structure *hsd; hsd = initialize_dim_structure(); set_dim_structure_entry(hsd, 0, "ss"); set_dim_structure_entry(hsd, 1, "fs"); return hsd; } void free_dim_structure(struct dim_structure *hsd) { if ( hsd == NULL ) return; free(hsd->dims); free(hsd); } static int parse_dim_structure_val(const char *val) { if ( strcmp(val,"%") == 0 ) { return HYSL_PLACEHOLDER; } else if ( strcmp(val,"ss") == 0 ) { return HYSL_SS; } else if ( strcmp(val,"fs") == 0 ) { return HYSL_FS; } return atoi(val); } int set_dim_structure_entry(struct dim_structure *hsd, int dim_entry, const char *val_string) { /* "dims" array needs element with zero index */ if ( dim_entry >= hsd->num_dims ) { int di; int *new_dims = realloc(hsd->dims, (dim_entry+1)*sizeof(int)); if ( new_dims == NULL ) return 1; /* Initialise the elements just allocated */ for ( di=hsd->num_dims; di<=dim_entry; di++ ) { new_dims[di] = HYSL_UNDEFINED; } hsd->dims = new_dims; hsd->num_dims = dim_entry+1; } hsd->dims[dim_entry] = parse_dim_structure_val(val_string); return 0; }