/*
* events.c
*
* Event properties
*
* Copyright © 2012-2017 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
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;
}
/**
* find_event:
* @ev: An event structure
* @el: An event list
*
* Returns: the indexing into @el of the event matching @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 *ret_string;
char *new_ret_string;
int ret_string_len;
if ( ev == NULL ) return strdup("(none)");
if ( ev->path_length != 0 ) {
int pi;
ret_string = strdup(ev->path_entries[0]);
ret_string_len = strlen(ret_string);
for ( pi=1; pipath_length; pi++ ) {
new_ret_string = realloc(ret_string,
(ret_string_len+1+strlen(ev->path_entries[pi]))
* sizeof(char));
if ( new_ret_string == NULL ) {
return NULL;
}
ret_string=new_ret_string;
strncpy(&ret_string[ret_string_len],"/", 1);
strncpy(&ret_string[ret_string_len+1],ev->path_entries[pi],
strlen(ev->path_entries[pi]));
ret_string_len += 1+strlen(ev->path_entries[pi]);
}
new_ret_string = realloc(ret_string,
(1+ret_string_len)*sizeof(char));
if ( new_ret_string == NULL ) {
return NULL;
}
ret_string = new_ret_string;
strncpy(&ret_string[ret_string_len], "/", 1);
ret_string_len += 1;
} else {
ret_string = strdup("/");
ret_string_len = 1;
}
if ( ev->dim_length !=0 ) {
char num_buf[64];
int di;
for ( di=0; didim_length; di++ ) {
sprintf(num_buf, "%i", ev->dim_entries[di]);
new_ret_string = realloc(ret_string,
(ret_string_len+1+strlen(num_buf))
*sizeof(char));
if ( new_ret_string == NULL ) {
return NULL;
}
ret_string = new_ret_string;
strncpy(&ret_string[ret_string_len],"/", 1);
strncpy(&ret_string[ret_string_len+1], num_buf,
strlen(num_buf));
ret_string_len += 1+strlen(num_buf);
}
} else {
new_ret_string = realloc(ret_string,
(1+ret_string_len)*sizeof(char));
if ( new_ret_string == NULL ) {
return NULL;
}
ret_string = new_ret_string;
strncpy(&ret_string[ret_string_len], "/", 1);
ret_string_len += 1;
}
new_ret_string = realloc(ret_string,
(1+ret_string_len)*sizeof(char));
if ( new_ret_string == NULL ) {
return NULL;
}
ret_string = new_ret_string;
strncpy(&ret_string[ret_string_len], "\0", 1);
return ret_string;
}
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;
}