diff options
Diffstat (limited to 'src/silx/io/specfile/src')
-rw-r--r-- | src/silx/io/specfile/src/locale_management.c | 79 | ||||
-rw-r--r-- | src/silx/io/specfile/src/sfdata.c | 757 | ||||
-rw-r--r-- | src/silx/io/specfile/src/sfheader.c | 792 | ||||
-rw-r--r-- | src/silx/io/specfile/src/sfindex.c | 556 | ||||
-rw-r--r-- | src/silx/io/specfile/src/sfinit.c | 830 | ||||
-rw-r--r-- | src/silx/io/specfile/src/sflabel.c | 654 | ||||
-rw-r--r-- | src/silx/io/specfile/src/sflists.c | 189 | ||||
-rw-r--r-- | src/silx/io/specfile/src/sfmca.c | 341 | ||||
-rw-r--r-- | src/silx/io/specfile/src/sftools.c | 554 | ||||
-rw-r--r-- | src/silx/io/specfile/src/sfwrite.c | 592 |
10 files changed, 5344 insertions, 0 deletions
diff --git a/src/silx/io/specfile/src/locale_management.c b/src/silx/io/specfile/src/locale_management.c new file mode 100644 index 0000000..0c5f7ca --- /dev/null +++ b/src/silx/io/specfile/src/locale_management.c @@ -0,0 +1,79 @@ +# /*########################################################################## +# Copyright (C) 2012-2017 European Synchrotron Radiation Facility +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# +# ############################################################################*/ +#include <locale_management.h> +#include <stdlib.h> + +#ifdef _GNU_SOURCE +# include <locale.h> +# ifdef __GLIBC__ +# include <features.h> +# if !((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ > 25))) +# /* strtod_l has been moved to stdlib.h since glibc 2.26 */ +# include <xlocale.h> +# endif +# else +# include <xlocale.h> +# endif +#else +# ifdef PYMCA_POSIX +# else +# ifdef SPECFILE_POSIX +# include <locale.h> +# ifndef LOCALE_NAME_MAX_LENGTH +# define LOCALE_NAME_MAX_LENGTH 85 +# endif +# endif +# endif +#endif + +#include <string.h> + +double PyMcaAtof(const char * inputString) +{ +#ifdef _GNU_SOURCE + double result; + locale_t newLocale; + newLocale = newlocale(LC_NUMERIC_MASK, "C", NULL); + result = strtod_l(inputString, NULL, newLocale); + freelocale(newLocale); + return result; +#else +#ifdef PYMCA_POSIX + return atof(inputString); +#else +#ifdef SPECFILE_POSIX + char *currentLocaleBuffer; + char localeBuffer[LOCALE_NAME_MAX_LENGTH + 1] = {'\0'}; + double result; + currentLocaleBuffer = setlocale(LC_NUMERIC, NULL); + strcpy(localeBuffer, currentLocaleBuffer); + setlocale(LC_NUMERIC, "C\0"); + result = atof(inputString); + setlocale(LC_NUMERIC, localeBuffer); + return(result); +#else + return atof(inputString); +#endif +#endif +#endif +} diff --git a/src/silx/io/specfile/src/sfdata.c b/src/silx/io/specfile/src/sfdata.c new file mode 100644 index 0000000..689f56d --- /dev/null +++ b/src/silx/io/specfile/src/sfdata.c @@ -0,0 +1,757 @@ +# /*########################################################################## +# Copyright (C) 1995-2017 European Synchrotron Radiation Facility +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# +# ############################################################################*/ +/************************************************************************ + * + * File: sfdata.c + * + * Project: SpecFile library + * + * Description: Functions for getting data + * + * Author: V.Rey + * + * Date: $Date: 2005/07/04 15:02:38 $ + * + ************************************************************************/ +/* + * Log: $Log: sfdata.c,v $ + * Log: Revision 1.8 2005/07/04 15:02:38 ahoms + * Log: Fixed memory leak in SfNoDataLines + * Log: + * Log: Revision 1.7 2004/01/20 09:23:50 sole + * Log: Small change in sfdata (ptr < (to-1)) changed to (ptr <= (to-1)) + * Log: + * Log: Revision 1.6 2003/03/06 16:56:40 sole + * Log: Check if to is beyond the scan size in SfData (still not finished but it seems to solve a crash) + * Log: + * Log: Revision 1.5 2002/12/09 13:04:05 sole + * Log: Added a check in SfNoDataLines + * Log: + * Log: Revision 1.4 2002/11/13 15:02:38 sole + * Log: Removed some printing in SfData + * Log: + * Log: Revision 1.3 2002/11/12 16:22:07 sole + * Log: WARNING: Developing version - Improved MCA reading and reading properly the end of the file. + * Log: + * Log: Revision 1.2 2002/11/12 13:15:52 sole + * Log: 1st version from Armando. The idea behind is to take the last line only if it ends with \n + * Log: + * Log: Revision 3.0 2000/12/20 14:17:19 rey + * Log: Python version available + * Log: + * Revision 2.1 2000/07/31 19:05:11 19:05:11 rey (Vicente Rey-Bakaikoa) + * SfUpdate and bug corrected in ReadIndex + * + * Revision 2.0 2000/04/13 13:28:54 13:28:54 rey (Vicente Rey-Bakaikoa) + * New version of the library. Complete rewrite + * Adds support for MCA + * + */ +#include <SpecFile.h> +#include <SpecFileP.h> +#include <locale_management.h> + +#ifndef _GNU_SOURCE +#ifdef PYMCA_POSIX +#include <locale.h> +#endif +#endif + +#include <ctype.h> +/* + * Define macro + */ +#define isnumber(this) ( isdigit(this) || this == '-' || this == '+' || this == '.' || this == 'E' || this == 'e') + +/* + * Mca continuation character + */ +#define MCA_CONT '\\' +#define D_INFO 3 + +/* + * Declarations + */ +DllExport long SfNoDataLines ( SpecFile *sf, long index, int *error ); +DllExport int SfData ( SpecFile *sf, long index, double ***retdata, + long **retinfo, int *error ); +DllExport long SfDataAsString ( SpecFile *sf, long index, + char ***data, int *error ); +DllExport long SfDataLine ( SpecFile *sf, long index, long line, + double **data_line, int *error ); +DllExport long SfDataCol ( SpecFile *sf, long index, long col, + double **data_col, int *error ); +DllExport long SfDataColByName( SpecFile *sf, long index, + char *label, double **data_col, int *error ); + + +/********************************************************************* + * Function: long SfNoDataLines( sf, index, error ) + * + * Description: Gets number of data lines in a scan + * + * Parameters: + * Input : (1) File pointer + * (2) Index + * Output: + * (3) error number + * Returns: + * Number of data lines , + * ( -1 ) => errors. + * Possible errors: + * SF_ERR_SCAN_NOT_FOUND + * + *********************************************************************/ +DllExport long +SfNoDataLines( SpecFile *sf, long index, int *error ) +{ + long *dinfo = NULL; + double **data = NULL; + long nrlines = 0; + int ret, i; + + ret = SfData(sf,index,&data,&dinfo,error); + + if (ret == -1) { + return(-1); + } + if (dinfo == (long *) NULL){ + return(-1); + } + if (dinfo[ROW] < 0){ + printf("Negative number of points!\n"); + /*free(dinfo);*/ + return(-1); + } + + nrlines = dinfo[ROW]; + + /* now free all stuff that SfData allocated */ + for (i = 0; i < nrlines; i++) + free(data[i]); + free(data); + free(dinfo); + + return nrlines; +} + + + +/********************************************************************* + * Function: int SfData(sf, index, data, data_info, error) + * + * Description: Gets data. + * Parameters: + * Input : (1) File pointer + * (2) Index + * Output: + * (3) Data array + * (4) Data info : [0] => no_lines + * [1] => no_columns + * [2] = ( 0 ) => regular + * ( 1 ) => not regular ! + * (5) error number + * Returns: + * ( 0 ) => OK + * ( -1 ) => errors occured + * Possible errors: + * SF_ERR_MEMORY_ALLOC + * SF_ERR_FILE_READ + * SF_ERR_SCAN_NOT_FOUND + * SF_ERR_LINE_NOT_FOUND + * + * Remark: The memory allocated should be freed by the application + * + *********************************************************************/ +DllExport int +SfData( SpecFile *sf, long index, double ***retdata, long **retinfo, int *error ) +{ + long *dinfo = NULL; + double **data = NULL; + double *dataline = NULL; + long headersize; + + char *ptr, + *from, + *to; + + char strval[100]; + double val; + double valline[512]; + long cols, + maxcol=512; + long rows; + int i; +#ifndef _GNU_SOURCE +#ifdef PYMCA_POSIX + char *currentLocaleBuffer; + char localeBuffer[21]; +#endif +#endif + + if (index <= 0 ){ + return(-1); + } + + if (sfSetCurrent(sf,index,error) == -1 ) + return(-1); + + + /* + * Copy if already there + */ + if (sf->data_info != (long *)NULL) { + dinfo = ( long * ) malloc ( sizeof(long) * D_INFO); + dinfo[ROW] = sf->data_info[ROW]; + dinfo[COL] = sf->data_info[COL]; + dinfo[REG] = sf->data_info[REG]; + data = ( double **) malloc ( sizeof(double *) * dinfo[ROW]); + for (i=0;i<dinfo[ROW];i++) { + data[i] = (double *)malloc (sizeof(double) * dinfo[COL]); + memcpy(data[i],sf->data[i],sizeof(double) * dinfo[COL]); + } + *retdata = data; + *retinfo = dinfo; + return(0); + } + /* + * else do the job + */ + + if ( ((SpecScan *)sf->current->contents)->data_offset == -1 ) { + *retdata = data; + *retinfo = dinfo; + return(-1); + } + + headersize = ((SpecScan *)sf->current->contents)->data_offset + - ((SpecScan *)sf->current->contents)->offset; + + from = sf->scanbuffer + headersize; + to = sf->scanbuffer + ((SpecScan *)sf->current->contents)->size; + if (to > sf->scanbuffer+sf->scansize){ + /* the -32 found "experimentaly" */ + ptr = sf->scanbuffer+sf->scansize - 32; + while (*ptr != '\n') ptr--; + to=ptr; + /*printf("I let it crash ...\n");*/ + } + i=0; + ptr = from; + rows = -1; + cols = -1; + /* + * Alloc memory + */ + if ( (data = (double **) malloc (sizeof(double *)) ) == (double **)NULL) { + *error = SF_ERR_MEMORY_ALLOC; + return(-1); + } + + if ( (dinfo = (long *) malloc(sizeof(long) * D_INFO) ) == (long *)NULL) { + free(data); + *error = SF_ERR_MEMORY_ALLOC; + return(-1); + } + ptr = from; + dinfo[ROW] = dinfo[COL] = dinfo[REG] = 0; + +#ifndef _GNU_SOURCE +#ifdef PYMCA_POSIX + currentLocaleBuffer = setlocale(LC_NUMERIC, NULL); + strcpy(localeBuffer, currentLocaleBuffer); + setlocale(LC_NUMERIC, "C\0"); +#endif +#endif + for ( ; ptr < to; ptr++) { + /* get a complete line */ + i=0; + cols=0; + /*I should be at the start of a line */ + while(*(ptr) != '\n'){ + if (*(ptr-1) == '\n'){ + /*I am at the start of a line */ + while(*ptr == '#'){ + if (ptr >= to) + break; + for (; ptr < to; ptr++){ + if (*ptr == '\n'){ + break; + } + }; + /* on exit is equal to newline */ + if (ptr < to) { + ptr++; + } + } + if (*ptr == '@') { + /* + * read all mca block: go while in buffer ( ptr < to - 1 ) + * and while a newline is preceded by a slash + */ + for ( ptr = ptr + 2; + (*ptr != '\n' || (*(ptr-1) == MCA_CONT)) && ptr < to ; + ptr++); + if (ptr >= to){ + break; + } + } + while(*ptr == '#'){ + if (ptr >= to) + break; + for (; ptr < to; ptr++){ + if (*ptr == '\n'){ + break; + } + }; + /* on exit is equal to newline */ + if (ptr < to) { + ptr++; + } + } + /* first characters of buffer + */ + while (*ptr == ' ' && ptr < to) ptr++; /* get rid of empty spaces */ + } + /* + * in the middle of a line + */ + if (*ptr == ' ' || *ptr == '\t' ) { + strval[i] = '\0'; + i = 0; + val = PyMcaAtof(strval); + valline[cols] = val; + cols++; + if (cols >= maxcol) return(-1); + while(*(ptr+1) == ' ' || *(ptr+1) == '\t') ptr++; + } else { + if isnumber(*ptr){ + strval[i] = *ptr; + i++; + } + } + if (ptr >= (to-1)){ + break; + } + ptr++; + } + if ((*(ptr)== '\n') && (i != 0)){ + strval[i] = '\0'; + val = PyMcaAtof(strval); + valline[cols] = val; + cols++; + if (cols >= maxcol) return(-1); + /*while(*(ptr+1) == ' ' || *(ptr+1) == '\t') ptr++;*/ + } + /*printf("%c",*ptr);*/ + /* diffract31 crash -> changed from i!=0 to i==0 */ + /*cols>0 necessary scan 59 of 31oct98 */ + if ((ptr < to) && (cols >0)) { + rows++; + /*cols++;*/ + if (cols >= maxcol) return(-1); + /* printf("Adding a new row, nrows = %ld, ncols= %ld\n",rows,cols);*/ + /*printf("info col = %d cols = %d\n", dinfo[COL], cols);*/ + if (dinfo[COL] != 0 && cols != dinfo[COL]) { + ; + /*diffract31 crash -> nextline uncommented */ + dinfo[REG] = 1; + } else { + dinfo[COL] = cols; + } + if(dinfo[COL]==cols){ + dataline = (double *)malloc(sizeof(double) * cols); + memcpy(dataline,valline,sizeof(double) * cols); + data = (double **) realloc ( data, sizeof(double) * (rows+1)); + data[rows] = dataline; + dinfo[ROW]=rows+1; + }else{ + printf("Error on scan %d line %d\n", (int) index, (int) (rows+1)); + /* just ignore the line instead of stopping there with a + break; */ + rows--; + } + } + } + +#ifndef _GNU_SOURCE +#ifdef PYMCA_POSIX + setlocale(LC_NUMERIC, localeBuffer); +#endif +#endif + /* + * make a copy in specfile structure + */ + if ( dinfo[ROW] != 0 && dinfo[REG] == 0) { + if (sf->data_info != (long *)NULL){ + printf("I should not be here!/n"); + sf->data_info[ROW] = dinfo[ROW]; + sf->data_info[COL] = dinfo[COL]; + sf->data_info[REG] = dinfo[REG]; + for (i=0;i<dinfo[ROW];i++) { + sf->data[i]= (double *)realloc (sf->data[i],sizeof(double) * dinfo[COL]); + if (sf->data[i] == (double *) NULL){ + printf("Realloc problem"); + return (-1); + } + memcpy(sf->data[i],data[i],sizeof(double) * dinfo[COL]); + } + *retdata = data; + *retinfo = dinfo; + return(0); + }else{ + sf->data_info = ( long * ) malloc ( sizeof(long) * D_INFO); + sf->data_info[ROW] = dinfo[ROW]; + sf->data_info[COL] = dinfo[COL]; + sf->data_info[REG] = dinfo[REG]; + sf->data = ( double **) malloc ( sizeof(double *) * dinfo[ROW]); + if (sf->data == (double **) NULL){ + printf("malloc1 problem"); + return (-1); + } + for (i=0;i<dinfo[ROW];i++) { + sf->data[i] = (double *)malloc (sizeof(double) * dinfo[COL]); + if (sf->data[i] == (double *) NULL){ + printf("malloc2 problem"); + return (-1); + } + memcpy(sf->data[i],data[i],sizeof(double) * dinfo[COL]); + } + } + } else { + if (dinfo[REG] == 0) { + ; + /*printf("Not Freeing data:!\n");*/ + /* I can be in the case of an mca without scan points */ + /*free(data); + return(-1);*/ + } + } + *retinfo = dinfo; + *retdata = data; + return( 0 ); +} + + +DllExport long +SfDataCol ( SpecFile *sf, long index, long col, double **retdata, int *error ) +{ + double *datacol=NULL; + + long *dinfo = NULL; + double **data = NULL; + + long selection; + int i,ret; + + ret = SfData(sf,index,&data,&dinfo,error); + + if (ret == -1) { + *error = SF_ERR_COL_NOT_FOUND; + *retdata = datacol; + return(-1); + } + + if (col < 0) { + selection = dinfo[COL] + col; + } else { + selection = col - 1; + } +if (selection > dinfo[COL] - 1) { +selection=dinfo[COL] - 1; +} + if ( selection < 0 || selection > dinfo[COL] - 1) { + *error = SF_ERR_COL_NOT_FOUND; + if ( dinfo != (long *)NULL) { + freeArrNZ((void ***)&data,dinfo[ROW]); + } + free(dinfo); + return(-1); + } + + datacol = (double *) malloc( sizeof(double) * dinfo[ROW]); + if (datacol == (double *)NULL) { + *error = SF_ERR_MEMORY_ALLOC; + if ( dinfo != (long *)NULL) + freeArrNZ((void ***)&data,dinfo[ROW]); + free(dinfo); + return(-1); + } + + for (i=0;i<dinfo[ROW];i++) { + datacol[i] = data[i][selection]; + } + + ret = dinfo[ROW]; + + if ( dinfo != (long *)NULL) + freeArrNZ((void ***)&data,dinfo[ROW]); + free(dinfo); + + *retdata = datacol; + return(ret); +} + + +DllExport long +SfDataLine( SpecFile *sf, long index, long line, double **retdata, int *error ) +{ + double *datarow=NULL; + + long *dinfo = NULL; + double **data = NULL; + + long selection; + int ret; + + ret = SfData(sf,index,&data,&dinfo,error); + + if (ret == -1) { + *error = SF_ERR_LINE_NOT_FOUND; + *retdata = datarow; + return(-1); + } + + if (line < 0) { + selection = dinfo[ROW] + line; + } else { + selection = line - 1; + } + + if ( selection < 0 || selection > dinfo[ROW] - 1) { + *error = SF_ERR_LINE_NOT_FOUND; + if ( dinfo != (long *)NULL) { + freeArrNZ((void ***)&data,dinfo[ROW]); + } + free(dinfo); + return(-1); + } + + datarow = (double *) malloc( sizeof(double) * dinfo[COL]); + if (datarow == (double *)NULL) { + *error = SF_ERR_MEMORY_ALLOC; + if ( dinfo != (long *)NULL) + freeArrNZ((void ***)&data,dinfo[ROW]); + free(dinfo); + return(-1); + } + + + memcpy(datarow,data[selection],sizeof(double) * dinfo[COL]); + + ret = dinfo[COL]; + + if ( dinfo != (long *)NULL) + freeArrNZ((void ***)&data,dinfo[ROW]); + free(dinfo); + + *retdata = datarow; + return(ret); +} + + +DllExport long +SfDataColByName( SpecFile *sf, long index, char *label, double **retdata, int *error ) +{ + + double *datacol; + + long *dinfo = NULL; + double **data = NULL; + + int i,ret; + + char **labels = NULL; + + long nb_lab, + idx; + + short tofree=0; + + if ( sfSetCurrent(sf,index,error) == -1) { + *retdata = (double *)NULL; + return(-1); + } + + if ( sf->no_labels != -1 ) { + nb_lab = sf->no_labels; + labels = sf->labels; + } else { + nb_lab = SfAllLabels(sf,index,&labels,error); + tofree = 1; + } + + if ( nb_lab == 0 || nb_lab == -1) { + *retdata = (double *)NULL; + return(-1); + } + + for (idx=0;idx<nb_lab;idx++) + if (!strcmp(label,labels[idx])) break; + + if ( idx == nb_lab ) { + if (tofree) freeArrNZ((void ***)&labels,nb_lab); + *error = SF_ERR_COL_NOT_FOUND; + *retdata = (double *)NULL; + return(-1); + } + + ret = SfData(sf,index,&data,&dinfo,error); + + if (ret == -1) { + *retdata = (double *)NULL; + return(-1); + } + + datacol = (double *) malloc( sizeof(double) * dinfo[ROW]); + if (datacol == (double *)NULL) { + *error = SF_ERR_MEMORY_ALLOC; + if ( dinfo != (long *)NULL) + freeArrNZ((void ***)&data,dinfo[ROW]); + free(dinfo); + *retdata = (double *)NULL; + return(-1); + } + + for (i=0;i<dinfo[ROW];i++) { + datacol[i] = data[i][idx]; + } + + ret = dinfo[ROW]; + + if ( dinfo != (long *)NULL) + freeArrNZ((void ***)&data,dinfo[ROW]); + free(dinfo); + + *retdata = datacol; + + return(ret); +} + + +DllExport long +SfDataAsString( SpecFile *sf, long index, char ***retdata, int *error ) +{ + char **data=NULL; + char oneline[300]; + + char *from, + *to, + *ptr, + *dataline; + + long headersize,rows; + int i; + + if (sfSetCurrent(sf,index,error) == -1 ) + return(-1); + + if ( ((SpecScan *)sf->current->contents)->data_offset == -1 ) { + *retdata = data; + return(-1); + } + + data = (char **) malloc (sizeof(char *)); + + headersize = ((SpecScan *)sf->current->contents)->data_offset + - ((SpecScan *)sf->current->contents)->offset; + + from = sf->scanbuffer + headersize; + to = sf->scanbuffer + ((SpecScan *)sf->current->contents)->size; + + rows = -1; + i = 0; + + /* + * first characters of buffer + */ + + ptr = from; + + if (isnumber(*ptr)) { + rows++; + oneline[i] = *ptr; + i++; + } else if (*ptr == '@') { + /* + * read all mca block: go while in buffer ( ptr < to - 1 ) + * and while a newline is preceded by a slash + */ + for ( ptr = ptr + 2; + (*(ptr+1) != '\n' || (*ptr == MCA_CONT)) && ptr < to - 1 ; + ptr++); + } + + /* + * continue + */ + ptr++; + + for ( ; ptr < to - 1; ptr++) { + /* + * check for lines and for mca + */ + if ( *(ptr-1) == '\n' ) { + + if ( i != 0 ) { + oneline[i-1] = '\0'; + i = 0; + + dataline = (char *)strdup(oneline); + data = (char **) realloc ( data, sizeof(char *) * (rows +1)); + data[rows] = dataline; + } + + if ( *ptr == '@') { /* Mca --> pass it all */ + for ( ptr = ptr + 2; + (*ptr != '\n' || (*(ptr-1) == MCA_CONT)) && ptr < to ; + ptr++); + } else if ( *ptr == '#') { /* Comment --> pass one line */ + for (ptr = ptr + 1; *ptr != '\n';ptr++); + } else if ( isnumber(*ptr) ) { + rows++; + oneline[i] = *ptr; + i++; + } + } else { + if (rows == -1) continue; + + oneline[i] = *ptr; + i++; + } + } + + /* + * last line + */ + + if (rows != -1 && i) { + oneline[i-1] = '\0'; + dataline = (char *)strdup(oneline); + data = (char **) realloc ( data, sizeof(char *) * (rows+1)); + data[rows] = dataline; + } + + *retdata = data; + return(rows+1); +} diff --git a/src/silx/io/specfile/src/sfheader.c b/src/silx/io/specfile/src/sfheader.c new file mode 100644 index 0000000..b669e33 --- /dev/null +++ b/src/silx/io/specfile/src/sfheader.c @@ -0,0 +1,792 @@ +# /*########################################################################## +# Copyright (C) 1995-2017 European Synchrotron Radiation Facility +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# +# ############################################################################*/ +/************************************************************************ + * + * File: sfheader.c + * + * Project: SpecFile library + * + * Description: Functions to access file and scan headers + * + * Author: V.Rey + * + * Date: $Date: 2002/11/20 09:01:29 $ + * + ************************************************************************/ +/* + * Log: $Log: sfheader.c,v $ + * Log: Revision 1.3 2002/11/20 09:01:29 sole + * Log: Added free(line); in SfTitle + * Log: + * Log: Revision 1.2 2002/11/14 16:18:48 sole + * Log: stupid bug removed + * Log: + * Log: Revision 1.1 2002/11/14 15:25:39 sole + * Log: Initial revision + * Log: + * Log: Revision 3.0 2000/12/20 14:17:19 rey + * Log: Python version available + * Log: + * Revision 2.1 2000/07/31 19:05:09 19:05:09 rey (Vicente Rey-Bakaikoa) + * SfUpdate and bug corrected in ReadIndex + * + * Revision 2.0 2000/04/13 13:28:54 13:28:54 rey (Vicente Rey-Bakaikoa) + * New version of the library. Complete rewrite + * Adds support for MCA + */ +#include <SpecFile.h> +#include <SpecFileP.h> + +/* + * Function Declaration + */ +DllExport char * SfCommand ( SpecFile *sf, long index, int *error ); +DllExport long SfNoColumns ( SpecFile *sf, long index, int *error ); +DllExport char * SfDate ( SpecFile *sf, long index, int *error ); +DllExport double * SfHKL ( SpecFile *sf, long index, int *error ); + +DllExport long SfEpoch ( SpecFile *sf, long index, int *error ); +DllExport char * SfUser ( SpecFile *sf, long index, int *error ); +DllExport char * SfTitle ( SpecFile *sf, long index, int *error ); +DllExport char * SfFileDate ( SpecFile *sf, long index, int *error ); +DllExport long SfNoHeaderBefore ( SpecFile *sf, long index, int *error ); +DllExport long SfGeometry ( SpecFile *sf, long index, + char ***lines, int *error); +DllExport long SfHeader ( SpecFile *sf, long index, char *string, + char ***lines, int *error); +DllExport long SfFileHeader ( SpecFile *sf, long index, char *string, + char ***lines, int *error); + +int sfGetHeaderLine ( SpecFile *sf, int from, char character, + char **buf,int *error); +/* + * Internal functions + */ +static char *sfFindWord ( char *line, char *word, int *error ); +static long sfFindLines ( char *from, char *to,char *string, + char ***lines,int *error); +static char *sfOneLine ( char *from, char *end, int *error); + + +/********************************************************************* + * Function: char *SfCommand( sf, index, error ) + * + * Description: Reads '#S' line ( without #S and scan number ). + * + * Parameters: + * Input : (1) File pointer + * (2) Index + * Output: + * (3) error number + * Returns: + * String pointer, + * NULL => errors. + * Possible errors: + * SF_ERR_MEMORY_ALLOC + * SF_ERR_FILE_READ + * SF_ERR_SCAN_NOT_FOUND + * SF_ERR_LINE_NOT_FOUND + * + * Remark: The memory allocated should be freed by the application + * + *********************************************************************/ +DllExport char * +SfCommand( SpecFile *sf, long index, int *error ) +{ + char *ret_line=NULL; + long cnt,start,length; + char *ptr; + + /* + * Choose scan + */ + if (sfSetCurrent(sf,index,error) == -1) + return(ret_line); + + cnt = 3; + for ( ptr = sf->scanbuffer + cnt; *ptr != ' ' ; ptr++,cnt++); + for ( ptr = sf->scanbuffer + cnt; *ptr == ' ' || *ptr == '\t'; ptr++,cnt++); + + start = cnt; + for ( ptr = sf->scanbuffer + cnt; *ptr != '\n' ; ptr++,cnt++); + + length = cnt - start; + + /* + * Return the rest . + */ + ret_line = (char *) malloc ( sizeof(char) * ( length + 1) ); + if (ret_line == (char *)NULL) { + *error = SF_ERR_MEMORY_ALLOC; + return(ret_line); + } + + ptr = sf->scanbuffer + start; + memcpy(ret_line,ptr,sizeof(char) * length ); + ret_line[length] = '\0'; + + return( ret_line ); +} + + +/********************************************************************* + * Function: long SfNoColumns( sf, index, error ) + * + * Description: Gets number of columns in a scan + * + * Parameters: + * Input : (1) File pointer + * (2) Index + * Output: + * (3) error number + * Returns: + * Number of scan columns.(From #N line !) + * ( -1 ) if errors occured. + * Possible errors: + * SF_ERR_MEMORY_ALLOC | => readHeader() + * SF_ERR_LINE_NOT_FOUND + * SF_ERR_FILE_READ + * SF_ERR_SCAN_NOT_FOUND + * + *********************************************************************/ +DllExport long +SfNoColumns( SpecFile *sf, long index, int *error ) +{ + long col = -1; + char *buf=NULL; + + if ( sfSetCurrent(sf,index,error) == -1) + return(-1); + + if ( sfGetHeaderLine( sf, FROM_SCAN, SF_COLUMNS, &buf, error) == -1) + return(-1); + col = atol( buf ); + free(buf); + return( col ); +} + + +/********************************************************************* + * Function: char *SfDate( sf, index, error ) + * + * Description: Gets date from scan header + * + * Parameters: + * Input : (1) File pointer + * (2) Index + * Output: + * (3) error number + * Returns: + * Date.(From #D line !), + * NULL => errors. + * Possible errors: + * SF_ERR_MEMORY_ALLOC | => readHeader() + * SF_ERR_LINE_NOT_FOUND + * SF_ERR_FILE_READ + * SF_ERR_SCAN_NOT_FOUND + * + * Remark: The memory allocated should be freed by the application + * + *********************************************************************/ +DllExport char * +SfDate(SpecFile *sf, long index, int *error ) +{ + char *line=NULL; + + if ( sfSetCurrent(sf,index,error) == -1 ) + return(line); + + if ( sfGetHeaderLine( sf, FROM_SCAN, SF_DATE, &line, error)) + return((char *)NULL); + + return( line ); +} + + +/********************************************************************* + * Function: double *SfHKL( sf, index, error ) + * + * Description: Reads '#Q' line. + * + * Parameters: + * Input : (1) File pointer + * (2) Index + * Output: + * (3) error number + * Returns: + * Poiter to a 3x1 dbl. array( HKL[0]=HKL[H]=H_value, + * HKL[1]=HKL[K]=K_value, + * HKL[2]=HKL[L]=L_value. + * NULL => errors. + * + * Possible errors: + * SF_ERR_LINE_EMPTY + * SF_ERR_FILE_READ + * SF_ERR_SCAN_NOT_FOUND + * SF_ERR_LINE_NOT_FOUND + * SF_ERR_MEMORY_ALLOC | => mulstrtod() + * + * Remark: The memory allocated should be freed by the application + * + *********************************************************************/ +DllExport double * +SfHKL( SpecFile *sf, long index, int *error ) +{ + char *line=NULL; + double *HKL = NULL; + long i; + + if ( sfSetCurrent(sf,index,error) == -1 ) + return((double *)NULL); + + if ( sfGetHeaderLine( sf, FROM_SCAN, SF_RECIP_SPACE, &line, error) == -1 ) + return((double *)NULL); + + /* + * Convert into double . + */ + i = mulstrtod( line, &HKL, error ); + free(line); + + if ( i < 0) + return( (double *)NULL ); + + if ( i != 3 ) { + *error = SF_ERR_LINE_EMPTY; + free( HKL ); + return( (double *)NULL ); + } + + return( HKL ); +} + + +/********************************************************************* + * Function: long SfEpoch( sf, index, error ) + * + * Description: Gets epoch from the last file header. + * + * Parameters: + * Input : (1) File pointer + * (2) Index + * Output: + * (3) error number + * Returns: + * Epoch.(From #E line !) + * ( -1 ) if errors occured. + * Possible errors: + * SF_ERR_MEMORY_ALLOC | => readHeader() + * SF_ERR_LINE_NOT_FOUND + * SF_ERR_FILE_READ + * SF_ERR_HEADER_NOT_FOUND + * SF_ERR_SCAN_NOT_FOUND + * + *********************************************************************/ +DllExport long +SfEpoch( SpecFile *sf, long index, int *error ) +{ + char *buf=NULL; + long epoch = -1; + + if ( sfSetCurrent(sf,index,error) == -1 ) + return(-1); + + if ( sfGetHeaderLine(sf,FROM_FILE,SF_EPOCH,&buf,error) == -1 ) + return(-1); + + epoch = atol( buf ); + free(buf); + + return( epoch ); +} + + +/********************************************************************* + * Function: char SfFileDate( sf, index, error ) + * + * Description: Gets date from the last file header + * + * Parameters: + * Input : (1) File pointer + * (2) Index + * Output: + * (3) error number + * Returns: + * Date.(From #D line !) + * NULL => errors. + * + * Possible errors: + * SF_ERR_MEMORY_ALLOC | => readHeader() + * SF_ERR_LINE_NOT_FOUND + * SF_ERR_LINE_EMPTY + * SF_ERR_FILE_READ + * SF_ERR_HEADER_NOT_FOUND + * SF_ERR_SCAN_NOT_FOUND + * + *********************************************************************/ +DllExport char * +SfFileDate( SpecFile *sf, long index, int *error ) +{ + char *date = NULL; + + if ( sfSetCurrent(sf,index,error) == -1 ) + return((char *)NULL); + + if ( sfGetHeaderLine(sf,FROM_FILE,SF_DATE,&date,error) == -1 ) + return((char *)NULL); + + return( date ); +} + + +/********************************************************************* + * Function: long SfNoHeaderBefore( sf, index, error ) + * + * Description: Gets number of scan header lines before data. + * + * Parameters: + * Input : (1) File pointer + * (2) Scan index + * Output: + * (3) error number + * Returns: + * Number of scan header lines before data , + * ( -1 ) => errors. + * Possible errors: + * SF_ERR_SCAN_NOT_FOUND + * + *********************************************************************/ +DllExport long +SfNoHeaderBefore( SpecFile *sf, long index, int *error ) +{ + if ( sfSetCurrent(sf,index,error) == -1 ) + return(-1); + + /* + * Obsolete... give some reasonable! + */ + return(-1); +} + + +/********************************************************************* + * Function: char *SfUser( sf, index, error ) + * + * Description: Gets spec user information from the last file header + * + * Parameters: + * Input : (1) File pointer + * (2) Index + * Output: + * (3) error number + * Returns: + * User.(From 1st #C line !) + * Possible errors: + * SF_ERR_MEMORY_ALLOC ||=> findWordInLine() + * SF_ERR_LINE_NOT_FOUND | + * SF_ERR_FILE_READ | + * SF_ERR_SCAN_NOT_FOUND | => getFirstFileC() + * SF_ERR_HEADER_NOT_FOUND | + * SF_ERR_USER_NOT_FOUND + * + *********************************************************************/ +DllExport char * +SfUser( SpecFile *sf, long index, int *error ) +{ + + char *line=NULL; + char *user; + char word[] = "User ="; + + if (sfSetCurrent(sf,index,error) == -1) + return((char *)NULL); + + if (sfGetHeaderLine( sf, FROM_FILE, SF_COMMENT, &line, error) == -1) + return((char *)NULL); + + /* + * Find user. + */ + user = sfFindWord( line, word, error ); + + if ( user == (char *) NULL) { + *error = SF_ERR_USER_NOT_FOUND; + return((char *)NULL); + } + + free(line); + return( user ); +} + + +/********************************************************************* + * Function: long SfTitle( sf, index, error ) + * + * Description: Gets spec title information from the last file header + * + * Parameters: + * Input : (1) File pointer + * (2) Index + * Output: + * (3) error number + * Returns: + * Title.(From 1st #C line !) + * NULL => errors. + * Possible errors: + * SF_ERR_LINE_EMPTY + * SF_ERR_MEMORY_ALLOC + * SF_ERR_LINE_NOT_FOUND | + * SF_ERR_FILE_READ | + * SF_ERR_SCAN_NOT_FOUND | => getFirstFileC() + * SF_ERR_HEADER_NOT_FOUND | + * + *********************************************************************/ +DllExport char * +SfTitle( SpecFile *sf, long index, int *error ) +{ + char *line=NULL; + char *title; + char *ptr; + long i; + + if (sfSetCurrent(sf,index,error) == -1) + return((char *)NULL); + + if (sfGetHeaderLine( sf, FROM_FILE, SF_COMMENT, &line, error) == -1) + return((char *)NULL); + + /* + * Get title.( first word ) + */ + ptr = line; + + for ( i=0,ptr=line ; *ptr!='\t' && *ptr!='\n' && *ptr!='\0' ; i++ ) { + if ( *ptr==' ' ) { + if ( *(++ptr)==' ' ) { + break; + } else ptr--; + } + ptr++; + } + + if ( i==0 ) { + *error = SF_ERR_LINE_EMPTY; + return( (char *)NULL ); + } + + title = (char *)malloc( sizeof(char) * ( i+1 ) ); + + if ( title == (char *)NULL ) { + *error = SF_ERR_MEMORY_ALLOC; + return( title ); + } + + memcpy( title, line, sizeof(char) * i ); + /* Next line added by Armando, it may be wrong */ + free(line); + title[i] = '\0'; + + return( title ); +} + + +DllExport long +SfGeometry ( SpecFile *sf, long index, char ***lines, int *error) +{ + char string[] = " \0"; + + string[0] = SF_GEOMETRY; + + return(SfHeader(sf,index,string,lines,error)); +} + + +DllExport long +SfHeader ( SpecFile *sf, long index, char *string, char ***lines, int *error) +{ + char *headbuf, + *endheader; + + long nb_found; + + if (sfSetCurrent(sf,index,error) == -1) + return(-1); + + headbuf = sf->scanbuffer; + endheader = sf->scanbuffer + sf->scansize; + + nb_found = sfFindLines(headbuf, endheader,string, lines,error); + + if (nb_found == 0) { + return SfFileHeader(sf,index,string,lines,error); + } else { + return nb_found; + } +} + + + +DllExport long +SfFileHeader ( SpecFile *sf, long index, char *string, char ***lines, int *error) +{ + char *headbuf, + *endheader; + + if (sfSetCurrent(sf,index,error) == -1) + return(-1); + if (sf->filebuffersize > 0) + { + headbuf = sf->filebuffer; + endheader = sf->filebuffer + sf->filebuffersize; + + return(sfFindLines(headbuf,endheader,string,lines,error)); + } + else + { + return 0; + } +} + + +static long +sfFindLines(char *from,char *to,char *string,char ***ret,int *error) +{ + char **lines; + long found; + unsigned long j; + char *ptr; + short all=0; + + found = 0; + ptr = from; + + if ( string == (char *) NULL || strlen(string) == 0) + all = 1; + + /* + * Allocate memory for an array of strings + */ + if ( (lines = (char **)malloc( sizeof(char *) )) == (char **)NULL ) { + *error = SF_ERR_MEMORY_ALLOC; + return ( -1 ); + } + + /* + * First line + */ + if ( ptr[0] == '#' ) { + if ( all ) { + lines = (char **) realloc ( lines, (found+1) * sizeof(char *) ); + lines[found] = sfOneLine(ptr,to,error); + found++; + } else if ( ptr[1] == string[0]) { + for ( j=0; j < strlen(string) && ptr+j< to;j++) + if ( ptr[j+1] != string[j]) break; + if ( j == strlen(string)) { + lines = (char **) realloc ( lines, (found+1) * sizeof(char *) ); + lines[found] = sfOneLine(ptr,to,error); + found++; + } + } + } + + /* + * The rest + */ + for ( ptr = from + 1;ptr < to - 1;ptr++) { + if ( *(ptr - 1) == '\n' && *ptr == '#' ) { + if ( all ) { + lines = (char **) realloc ( lines, (found+1) * sizeof(char *) ); + lines[found] = sfOneLine(ptr,to,error); + found++; + } else if ( *(ptr+1) == string[0]) { + for ( j=0; j < strlen(string) && (ptr + j) < to;j++) + if ( ptr[j+1] != string[j]) break; + if ( j == strlen(string)) { + lines = (char **) realloc ( lines, (found+1) * sizeof(char *) ); + lines[found] = sfOneLine(ptr,to,error); + found++; + } + } + } + } + + if (found) *ret = lines; + else free(lines); + + return(found); +} + + +/********************************************************************* + * Function: char *sfGetHeaderLine( SpecFile *sf, sf_char, end, error ) + * + * Description: Gets one '#sf_char' line. + * + * Parameters: + * Input : (1) File pointer + * (2) sf_character + * (3) end ( where to stop the search ) + * Output: + * (4) error number + * Returns: + * Pointer to the line , + * NULL in case of errors. + * Possible errors: + * SF_ERR_MEMORY_ALLOC + * SF_ERR_FILE_READ | => findLine() + * + * Remark: The memory allocated should be freed by the application + * + *********************************************************************/ +int +sfGetHeaderLine( SpecFile *sf, int from , char sf_char, char **buf, int *error) +{ + + char *ptr,*headbuf; + char *endheader; + int found; + + found = 0; + + if ( from == FROM_SCAN ) { + headbuf = sf->scanbuffer; + endheader = sf->scanbuffer + sf->scanheadersize; + } else if ( from == FROM_FILE ) { + if ( sf->filebuffersize == 0 ) { + *error = SF_ERR_LINE_NOT_FOUND; + return(-1); + } + headbuf = sf->filebuffer; + endheader = sf->filebuffer + sf->filebuffersize; + } else { + *error = SF_ERR_LINE_NOT_FOUND; + return(-1); + } + + if ( headbuf[0] == '#' && headbuf[1] == sf_char) { + found = 1; + ptr = headbuf; + } else { + for ( ptr = headbuf + 1;ptr < endheader - 1;ptr++) { + if ( *(ptr - 1) == '\n' && *ptr == '#' && *(ptr+1) == sf_char) { + found = 1; + break; + } + } + } + + if (!found) { + *error = SF_ERR_LINE_NOT_FOUND; + return(-1); + } + + /* + * Beginning of the thing after '#X ' + */ + ptr = ptr + 3; + + *buf = sfOneLine(ptr,endheader,error); + + return( 0 ); +} + +static char * +sfOneLine(char *from,char *end,int *error) +{ + static char linebuf[5000]; + + char *ptr,*buf; + long i; + + ptr = from; + + for(i=0;*ptr != '\n' && ptr < end;ptr++,i++) { + linebuf[i] = *ptr; + } + + linebuf[i]='\0'; + + buf = (char *) malloc ( i+1 ); + + if (buf == ( char * ) NULL ) { + *error = SF_ERR_MEMORY_ALLOC; + return((char *)NULL); + } + strcpy(buf,(char *)linebuf); + + return(buf); +} + + +/********************************************************************* + * Function: char *sfFindWord( line, word, error ) + * + * Description: Looks for 'word' in given line and returns a + * copy of the rest of the line after the found word . + * + * Parameters: + * Input : (1) Line pointer + * (2) Word pointer + * Output: + * (3) error number + * Returns: + * Rest of the line after word. + * NULL => not found. + * Possible errors: + * SF_ERR_MEMORY_ALLOC + * + *********************************************************************/ +static char * +sfFindWord( char *line, char *word, int *error ) +{ + char *ret; + + line = strstr( line, word ); + + if ( line == (char *)NULL ) { + return( line ); + } + + line += strlen( word ); + + /* + * Delete blanks. + */ + while ( *line == ' ' || *line == '\t' ) line++; + + /* + * Copy the rest. + */ + ret = (char *)malloc( sizeof(char) * ( 1 + strlen( line )) ); + + if ( ret == (char *)NULL ) { + *error = SF_ERR_MEMORY_ALLOC; + return(ret); + } + + memcpy( ret, line, sizeof(char) * ( 1 + strlen( line )) ); + + return( ret ); +} + diff --git a/src/silx/io/specfile/src/sfindex.c b/src/silx/io/specfile/src/sfindex.c new file mode 100644 index 0000000..320b086 --- /dev/null +++ b/src/silx/io/specfile/src/sfindex.c @@ -0,0 +1,556 @@ +# /*########################################################################## +# Copyright (C) 1995-2017 European Synchrotron Radiation Facility +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# +# ############################################################################*/ +/************************************************************************ + * + * File: sfindex.c + * + * Project: SpecFile library + * + * Description: functions for scan numbering + * + * Author: V.Rey + * + * Date: $Date: 2004/05/12 16:56:47 $ + * + ************************************************************************/ +/* + * Log: $Log: sfindex.c,v $ + * Log: Revision 1.2 2004/05/12 16:56:47 sole + * Log: Support for windows + * Log: + * Log: Revision 1.1 2003/03/06 16:59:05 sole + * Log: Initial revision + * Log: + * Log: Revision 3.0 2000/12/20 14:17:19 rey + * Log: Python version available + * Log: + * Revision 2.1 2000/07/31 19:05:15 19:05:15 rey (Vicente Rey-Bakaikoa) + * SfUpdate and bug corrected in ReadIndex + * + * Revision 2.0 2000/04/13 13:28:54 13:28:54 rey (Vicente Rey-Bakaikoa) + * New version of the library. Complete rewrite + * Adds support for MCA + */ +/* + * File: sfindex.c + * + * Description: + * + * Project: + * + * Author: Vicente Rey Bakaikoa + * + * Date: March 2000 + */ +/* + * $Log: sfindex.c,v $ + * Revision 1.2 2004/05/12 16:56:47 sole + * Support for windows + * + * Revision 1.1 2003/03/06 16:59:05 sole + * Initial revision + * + * Revision 3.0 2000/12/20 14:17:19 rey + * Python version available + * + * Revision 2.1 2000/07/31 19:05:15 19:05:15 rey (Vicente Rey-Bakaikoa) + * SfUpdate and bug corrected in ReadIndex + * + * Revision 2.0 2000/04/13 13:26:55 13:26:55 rey (Vicente Rey-Bakaikoa) + * New version of the library. Complete rewrite + * Adds support for MCA + * + */ + +#include <SpecFile.h> +#include <SpecFileP.h> +#ifdef WIN32 +#include <stdio.h> +#include <stdlib.h> +#else +#include <unistd.h> +#endif +#include <ctype.h> + +#define ON_COMMENT 0 +#define ON_ABO 1 +#define ON_RES 2 +/* + * Declarations + */ +DllExport long * SfList ( SpecFile *sf, int *error ); +DllExport long SfIndexes ( SpecFile *sf, long number, long **idxlist ); +DllExport long SfIndex ( SpecFile *sf, long number, long order ); +DllExport long SfCondList ( SpecFile *sf, long cond, long **scan_list, + int *error ); +DllExport long SfScanNo ( SpecFile *sf ); +DllExport int SfNumberOrder ( SpecFile *sf, long index, long *number, + long *order ); +DllExport long SfNumber ( SpecFile *sf, long index ); +DllExport long SfOrder ( SpecFile *sf, long index ); + +/* + * Internal Functions + */ +static int checkAborted( SpecFile *sf, ObjectList *ptr, int *error ); + + +/********************************************************************* + * Function: long *SfList( sf, error ) + * + * Description: Creates an array with all scan numbers. + * + * Parameters: + * Input : SpecFile pointer + * Returns: + * Array with scan numbers. + * NULL if errors occured. + * Possible errors: + * SF_ERR_MEMORY_ALLOC + * + * Remark: The memory allocated should be freed by the application + * + *********************************************************************/ +DllExport long * +SfList( SpecFile *sf, int *error ) +{ + register ObjectList *ptr; + long *scan_list; + long i = 0; + + scan_list = (long *)malloc( sizeof(long) * (sf->no_scans) ); + + if ( scan_list == (long *)NULL ) { + *error = SF_ERR_MEMORY_ALLOC; + return( scan_list ); + } + + for ( ptr=sf->list.first ; ptr ; ptr=ptr->next ,i++) { + scan_list[i] = ( ((SpecScan *)(ptr->contents))->scan_no ); + } + /*printf("scanlist[%li] = %li\n",i-1,scan_list[i-1]);*/ + return( scan_list ); +} + + +/********************************************************************* + * Function: long SfIndexes( sf, number , idxlist) + * + * Description: Creates an array with all indexes with the same scan + * number. + * + * Parameters: + * Input : SpecFile pointer + * scan number + * Output : array with scan indexes + * Returns: + * Number of indexes found + * Possible errors: + * None possible + * + * Remark: The memory allocated should be freed by the application + * + *********************************************************************/ +DllExport long +SfIndexes( SpecFile *sf, long number, long **idxlist ) +{ + ObjectList *ptr; + long i; + long *indexes; + long *arr; + + i = 0; + indexes = (long *)malloc(sf->no_scans * sizeof(long)); + + for (ptr = sf->list.first; ptr; ptr=ptr->next ) { + if ( number == ((SpecScan *)(ptr->contents))->scan_no) { + indexes[i] = ((SpecScan *)(ptr->contents))->index; + i++; + } + } + + if (i == 0) + arr = (long *) NULL; + else { + arr = (long *)malloc(sizeof(long) * i); + memcpy(arr,indexes,sizeof(long) * i); + } + + *idxlist = arr; + free(indexes); + return( i ); +} + + +/********************************************************************* + * Function: long SfIndex( sf, number, order ) + * + * Description: Gets scan index from scan number and order. + * + * Parameters: + * Input : (1) Scan number + * (2) Scan order + * Returns: + * Index number. + * (-1) if not found. + * + *********************************************************************/ +DllExport long +SfIndex( SpecFile *sf, long number, long order ) +{ + ObjectList *ptr; + + ptr = findScanByNo( &(sf->list), number, order ); + if ( ptr != (ObjectList *)NULL ) + return( ((SpecScan *)(ptr->contents))->index ); + + return( -1 ); +} + + +/********************************************************************* + * Function: long SfCondList( sf, cond, scan_list, error ) + * + * Description: Creates an array with all scan numbers. + * + * Parameters: + * Input : (1) SpecFile pointer + * (2) Condition : 0 => not aborted scans ( NOT_ABORTED ) + * -1 => aborted scans ( ABORTED ) + * nn => more than 'nn' data lines + * Output: (3) Scan list + * (4) error code + * Returns: + * Number of found scans. + * ( -1 ) if errors occured. + * Possible errors: + * SF_ERR_MEMORY_ALLOC + * + * Remark: The memory allocated should be freed by the application + * + *********************************************************************/ +DllExport long +SfCondList( SpecFile *sf, long cond, long **scan_list, int *error ) +{ + register ObjectList *ptr; + long *list; + long i = 0; + int retcheck; + long index; + + *scan_list = (long *)NULL; + + list = (long *)malloc( sizeof(long) * (sf->no_scans) ); + + if ( list == (long *)NULL ) { + *error = SF_ERR_MEMORY_ALLOC; + return( -1 ); + } + + /* + * Aborted scans . + */ + if ( cond < 0 ) { /* aborted scans */ + for ( ptr=sf->list.first ; ptr ; ptr=ptr->next ) { + + retcheck = checkAborted( sf, ptr, error ); + + if ( retcheck < 0 ) { + free( list ); + return( -1 ); + } else if ( retcheck > 0) { + list[i] = ( ((SpecScan *)(ptr->contents))->scan_no ); + i++; + } + } + } else if ( cond == 0 ) { /* not aborted scans */ + for ( ptr=sf->list.first ; ptr ; ptr=ptr->next ) { + + retcheck = checkAborted( sf, ptr, error ); + + if ( retcheck < 0 ) { + free( list ); + return( -1 ); + } else if ( retcheck == 0 ) { + list[i] = ( ((SpecScan *)(ptr->contents))->scan_no ); + i++; + } + } + } else { /* cond > 0 - more than n data_lines */ + for ( ptr=sf->list.first ; ptr ; ptr=ptr->next ) { + + index = ( ((SpecScan *)(ptr->contents))->index ); + if ( SfNoDataLines(sf,index,error) <= cond ) continue; + + list[i] = ( ((SpecScan *)(ptr->contents))->scan_no ); + i++; + } + } + + *scan_list = ( long * ) malloc ( i * sizeof(long)); + + if ( *scan_list == (long *)NULL ) { + *error = SF_ERR_MEMORY_ALLOC; + return( -1 ); + } + + memcpy(*scan_list,list, i * sizeof(long)); + free(list); + + return( i ); +} + + +/********************************************************************* + * Function: long SfScanNo( sf ) + * + * Description: Gets number of scans. + * + * Parameters: + * Input :(1) SpecFile pointer + * Returns: + * Number of scans. + * + *********************************************************************/ +DllExport long +SfScanNo( SpecFile *sf ) +{ + return( sf->no_scans ); +} + + +/********************************************************************* + * Function: int SfNumberOrder( sf, index, number, order ) + * + * Description: Gets scan number and order from index. + * + * Parameters: + * Input : + * (1) SpecFile pointer + * (2) Scan index + * Output: + * (3) Scan number + * (4) Scan order + * Returns: + * ( -1 ) => not found + * ( 0 ) => found + * + *********************************************************************/ +DllExport int +SfNumberOrder( SpecFile *sf, long index, long *number, long *order ) +{ + register ObjectList *list; + + *number = -1; + *order = -1; + + /* + * Find scan . + */ + list = findScanByIndex( &(sf->list), index ); + if ( list == (ObjectList *)NULL ) return( -1 ); + + *number = ((SpecScan *)list->contents)->scan_no; + *order = ((SpecScan *)list->contents)->order; + + return( 0 ); +} + + +/********************************************************************* + * Function: long SfNumber( sf, index ) + * + * Description: Gets scan number from index. + * + * Parameters: + * Input : (1) SpecFile pointer + * (2) Scan index + * Returns: + * Scan number. + * ( -1 ) => not found + * + *********************************************************************/ +DllExport long +SfNumber( SpecFile *sf, long index ) +{ + register ObjectList *list; + + /* + * Find scan . + */ + list = findScanByIndex( &(sf->list), index ); + if ( list == (ObjectList *)NULL ) return( -1 ); + + return( ((SpecScan *)list->contents)->scan_no ); +} + + +/********************************************************************* + * Function: long SfOrder( sf, index ) + * + * Description: Gets scan order from index. + * + * Parameters: + * Input : (1) SpecFile pointer + * (2) Scan index + * Returns: + * Scan order. + * ( -1 ) => not found + * + *********************************************************************/ +DllExport long +SfOrder( SpecFile *sf, long index ) +{ + register ObjectList *list; + + + /* + * Find scan . + */ + list = findScanByIndex( &(sf->list), index ); + if ( list == (ObjectList *)NULL ) return( -1 ); + + return( ((SpecScan *)list->contents)->order ); +} + +/********************************************************************* + * Function: int checkAborted( sf, ptr, error ) + * + * Description: Checks if scan was aborted or not . + * + * Parameters: + * Input : (1) SpecScan pointer + * (2) Pointer to the scan + * Output: (3) Error number + * Returns: + * (-1 ) : error + * ( 0 ) : not aborted + * ( 1 ) : aborted + * Possible errors: + * SF_ERR_MEMORY_ALLOC | => readHeader() + * SF_ERR_FILE_READ + * + *********************************************************************/ +static int +checkAborted( SpecFile *sf, ObjectList *ptr, int *error ) +{ + long nbytes; + long data_lines,size,from; + SpecScan *scan; + char *buffer,*cptr,next; + int state=ON_COMMENT; + int aborted=0; + long index; + + scan = ptr->contents; + index = scan->index; + + data_lines = SfNoDataLines(sf,index,error); + + if ( scan->hdafter_offset == -1 && data_lines > 0) { + return(0); + } else if ( data_lines <= 0 ) { + /* + * maybe aborted on first point + * we have to all to know ( but no data anyway ) + */ + size = scan->size; + from = scan->offset; + } else { + size = scan->last - scan->hdafter_offset; + from = scan->hdafter_offset; + } + + lseek(sf->fd,from,SEEK_SET); + buffer = ( char * ) malloc (size); + nbytes = read(sf->fd,buffer,size); + + if (nbytes == -1 ) { + *error = SF_ERR_FILE_READ; + return(-1); + } + + if (buffer[0] == '#' && buffer[1] == 'C') { + state = ON_COMMENT; + } + + for ( cptr = buffer + 1; cptr < buffer + nbytes - 1; cptr++) { + /* + * Comment line + */ + if ( *cptr == '#' && *(cptr+1) == 'C' && *(cptr-1) == '\n') { + state = ON_COMMENT; + } + /* + * Check aborted + */ + if ( *(cptr-1) == 'a' && *cptr == 'b' && *(cptr+1) == 'o') { + if ( state == ON_COMMENT ) { + state = ON_ABO; + } + } + if ( *(cptr-1) == 'r' && *cptr == 't' && *(cptr+1) == 'e') { + if ( state == ON_ABO) { + aborted = 1; + } + } + /* + * Check resume line + */ + if ( *(cptr-1) == 'r' && *cptr == 'e' && *(cptr+1) == 's') { + if ( state == ON_COMMENT ) { + state = ON_RES; + } + } + if ( *(cptr-1) == 'u' && *cptr == 'm' && *(cptr+1) == 'e') { + if ( state == ON_RES) { + aborted = 0; + } + } + + /* + * If data line... aborted is aborted + */ + if ( *cptr == '\n' ) { + next = *(cptr+1); + if (isdigit(next) || next == '+' || next == '-' || next == '@') { + aborted = 0; + } + } + } + free(buffer); + return(aborted); + +/* + * To be implemented + * - return 0 = not aborted + * - return 1 = aborted + * - return -1 = error + * + * implementation: read whole scan + * - go to header after offset + * - read all till end of scan with size + * - search for a line with a) #C ( comment ) then "aborted" + */ + return( 0 ); +} diff --git a/src/silx/io/specfile/src/sfinit.c b/src/silx/io/specfile/src/sfinit.c new file mode 100644 index 0000000..ca2fa7f --- /dev/null +++ b/src/silx/io/specfile/src/sfinit.c @@ -0,0 +1,830 @@ +# /*########################################################################## +# Copyright (C) 1995-2018 European Synchrotron Radiation Facility +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# +# ############################################################################*/ +/************************************************************************ + * + * File: sfinit.c + * + * Project: SpecFile library + * + * Description: Initialization routines ( open/update/close ) + * + * Author: V.Rey + * + * Date: $Date: 2005/05/25 13:01:32 $ + * + ************************************************************************/ +/* + * Log: $Log: sfinit.c,v $ + * Log: Revision 1.5 2005/05/25 13:01:32 sole + * Log: Back to revision 1.3 + * Log: + * Log: Revision 1.3 2004/05/12 16:57:32 sole + * Log: windows support + * Log: + * Log: Revision 1.2 2002/11/12 13:23:43 sole + * Log: Version with added support for the new sf->updating flag + * Log: + * Log: Revision 3.0 2000/12/20 14:17:19 rey + * Log: Python version available + * Log: + * Log: Revision 2.2 2000/12/20 12:12:08 rey + * Log: bug corrected with SfAllMotors + * Log: + * Revision 2.1 2000/07/31 19:04:42 19:04:42 rey (Vicente Rey-Bakaikoa) + * SfUpdate and bug corrected in ReadIndex + * + * Revision 2.0 2000/04/13 13:28:54 13:28:54 rey (Vicente Rey-Bakaikoa) + * New version of the library. Complete rewrite + * Adds support for MCA + */ +/* + * File: sfinit.c + * + * Description: This file implements basic routines on SPEC datafiles + * SfOpen / SfClose / SfError + * + * SfUpdate is kept but it is obsolete + * + * Version: 2.0 + * + * Date: March 2000 + * + * Author: Vicente REY + * + * Copyright: E.S.R.F. European Synchrotron Radiation Facility (c) 2000 + */ +/* + * $Log: sfinit.c,v $ + * Revision 1.5 2005/05/25 13:01:32 sole + * Back to revision 1.3 + * + * Revision 1.3 2004/05/12 16:57:32 sole + * windows support + * + * Revision 1.2 2002/11/12 13:23:43 sole + * Version with added support for the new sf->updating flag + * + * Revision 3.0 2000/12/20 14:17:19 rey + * Python version available + * + * Revision 2.2 2000/12/20 12:12:08 rey + * bug corrected with SfAllMotors + * + * Revision 2.1 2000/07/31 19:04:42 19:04:42 rey (Vicente Rey-Bakaikoa) + * SfUpdate and bug corrected in ReadIndex + * + * Revision 2.0 2000/04/13 13:27:19 13:27:19 rey (Vicente Rey-Bakaikoa) + * New version of the library. Complete rewrite + * Adds support for MCA + * + * + *********************************************************************/ +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> +#include <fcntl.h> +#include <ctype.h> + +#ifdef WIN32 +#include <stdio.h> +#include <stdlib.h> +#else +#include <unistd.h> +#endif + +#include <SpecFile.h> +#include <SpecFileP.h> + +/* + * Defines + */ + +#define ANY 0 +#define NEWLINE 1 +#define COMMENT 2 + +#define SF_ISFX ".sfI" + +#define SF_INIT 0 +#define SF_READY 1 +#define SF_MODIFIED 2 + +/* + * Function declaration + */ + +DllExport SpecFile * SfOpen ( char *name,int *error); +DllExport SpecFile * SfOpen2 ( int fd, char *name,int *error); +DllExport int SfClose ( SpecFile *sf); +DllExport short SfUpdate ( SpecFile *sf, int *error); +DllExport char * SfError ( int error); + + +#ifdef linux +char SF_SIGNATURE[] = "Linux 2ruru Sf2.0"; +#else +char SF_SIGNATURE[] = "2ruru Sf2.0"; +#endif + +/* + * Internal functions + */ +static short statusEnd ( char c2, char c1); +static void sfStartBuffer ( SpecFile *sf, SfCursor *cursor, short status,char c0, char c1,int *error); +static void sfNewLine ( SpecFile *sf, SfCursor *cursor, char c0,char c1,int *error); +static void sfHeaderLine ( SpecFile *sf, SfCursor *cursor, char c,int *error); +static void sfNewBlock ( SpecFile *sf, SfCursor *cursor, short how,int *error); +static void sfSaveScan ( SpecFile *sf, SfCursor *cursor, int *error); +static void sfAssignScanNumbers (SpecFile *sf); +static void sfReadFile ( SpecFile *sf, SfCursor *cursor, int *error); +static void sfResumeRead ( SpecFile *sf, SfCursor *cursor, int *error); +#ifdef SPECFILE_USE_INDEX_FILE +static short sfOpenIndex ( SpecFile *sf, SfCursor *cursor, int *error); +static short sfReadIndex ( int sfi, SpecFile *sf, SfCursor *cursor, int *error); +static void sfWriteIndex ( SpecFile *sf, SfCursor *cursor, int *error); +#endif + +/* + * errors + */ +typedef struct _errors { + int code; + char *message; +} sf_errors ; + +static +sf_errors errors[]={ +{ SF_ERR_MEMORY_ALLOC , "Memory allocation error ( SpecFile )" }, +{ SF_ERR_FILE_OPEN , "File open error ( SpecFile )" }, +{ SF_ERR_FILE_CLOSE , "File close error ( SpecFile )" }, +{ SF_ERR_FILE_READ , "File read error ( SpecFile )" }, +{ SF_ERR_FILE_WRITE , "File write error ( SpecFile )" }, +{ SF_ERR_LINE_NOT_FOUND , "Line not found error ( SpecFile )" }, +{ SF_ERR_SCAN_NOT_FOUND , "Scan not found error ( SpecFile )" }, +{ SF_ERR_HEADER_NOT_FOUND , "Header not found error ( SpecFile )" }, +{ SF_ERR_LABEL_NOT_FOUND , "Label not found error ( SpecFile )" }, +{ SF_ERR_MOTOR_NOT_FOUND , "Motor not found error ( SpecFile )" }, +{ SF_ERR_POSITION_NOT_FOUND , "Position not found error ( SpecFile )" }, +{ SF_ERR_LINE_EMPTY , "Line empty or wrong data error ( SpecFile )"}, +{ SF_ERR_USER_NOT_FOUND , "User not found error ( SpecFile )" }, +{ SF_ERR_COL_NOT_FOUND , "Column not found error ( SpecFile )" }, +{ SF_ERR_MCA_NOT_FOUND , "Mca not found ( SpecFile )" }, +/* MUST be always the last one : */ +{ SF_ERR_NO_ERRORS , "OK ( SpecFile )" }, +}; + + + + + +/********************************************************************* + * Function: SpecFile *SfOpen( name, error) + * + * Description: Opens connection to Spec data file. + * Creates index list in memory. + * + * Parameters: + * Input : + * (1) Filename + * Output: + * (2) error number + * Returns: + * SpecFile pointer. + * NULL if not successful. + * + * Possible errors: + * SF_ERR_FILE_OPEN + * SF_ERR_MEMORY_ALLOC + * + *********************************************************************/ + +DllExport SpecFile * +SfOpen(char *name, int *error) { + + int fd; + fd = open(name,SF_OPENFLAG); + return (SfOpen2(fd, name, error)); +} + + + +/********************************************************************* + * Function: SpecFile *SfOpen2( fd, name, error) + * + * Description: Opens connection to Spec data file. + * Creates index list in memory. + * + * Parameters: + * Input : + * (1) Integer file handle + * (2) Filename + * Output: + * (3) error number + * Returns: + * SpecFile pointer. + * NULL if not successful. + * + * Possible errors: + * SF_ERR_FILE_OPEN + * SF_ERR_MEMORY_ALLOC + * + *********************************************************************/ + +DllExport SpecFile * +SfOpen2(int fd, char *name,int *error) { + SpecFile *sf; + short idxret; + SfCursor cursor; + struct stat mystat; + + if ( fd == -1 ) { + *error = SF_ERR_FILE_OPEN; + return ( (SpecFile *) NULL ); + } + + /* + * Init specfile strucure + */ +#ifdef _WINDOWS + static HANDLE hglb; + hglb = GlobalAlloc(GPTR,sizeof(SpecFile)); + sf = (SpecFile * ) GlobalLock(hglb); +#else + sf = (SpecFile *) malloc ( sizeof(SpecFile )); +#endif + stat(name,&mystat); + + sf->fd = fd; + sf->m_time = mystat.st_mtime; + sf->sfname = (char *)strdup(name); + + sf->list.first = (ObjectList *)NULL; + sf->list.last = (ObjectList *)NULL; + sf->no_scans = 0; + sf->current = (ObjectList *)NULL; + sf->scanbuffer = (char *)NULL; + sf->scanheadersize = 0; + sf->filebuffer = (char *)NULL; + sf->filebuffersize = 0; + + sf->no_labels = -1; + sf->labels = (char **)NULL; + sf->no_motor_names = -1; + sf->motor_names = (char **)NULL; + sf->no_motor_pos = -1; + sf->motor_pos = (double *)NULL; + sf->data = (double **)NULL; + sf->data_info = (long *)NULL; + sf->updating = 0; + + /* + * Init cursor + */ + cursor.bytecnt = 0; + cursor.cursor = 0; + cursor.scanno = 0; + cursor.hdafoffset = -1; + cursor.dataoffset = -1; + cursor.mcaspectra = 0; + cursor.what = 0; + cursor.data = 0; + cursor.file_header = 0; + + +#ifdef SPECFILE_USE_INDEX_FILE + /* + * Check if index file + * open it and continue from there + */ + idxret = sfOpenIndex(sf,&cursor,error); +#else + idxret = SF_INIT; +#endif + + switch(idxret) { + case SF_MODIFIED: + sfResumeRead(sf,&cursor,error); + sfReadFile(sf,&cursor,error); + break; + + case SF_INIT: + sfReadFile(sf,&cursor,error); + break; + + case SF_READY: + break; + + default: + break; + } + + sf->cursor = cursor; + + /* + * Once is all done assign scan numbers and orders + */ + sfAssignScanNumbers(sf); + +#ifdef SPECFILE_USE_INDEX_FILE + if (idxret != SF_READY) sfWriteIndex(sf,&cursor,error); +#endif + return(sf); +} + + + + +/********************************************************************* + * + * Function: int SfClose( sf ) + * + * Description: Closes a file previously opened with SfOpen() + * and frees all memory . + * Parameters: + * Input: + * File pointer + * Returns: + * 0 : close successful + * -1 : errors occured + * + *********************************************************************/ +DllExport int +SfClose( SpecFile *sf ) +{ + register ObjectList *ptr; + register ObjectList *prevptr; + + freeAllData(sf); + + for( ptr=sf->list.last ; ptr ; ptr=prevptr ) { + free( (SpecScan *)ptr->contents ); + prevptr = ptr->prev; + free( (ObjectList *)ptr ); + } + + free ((char *)sf->sfname); + if (sf->scanbuffer != NULL) + free ((char *)sf->scanbuffer); + + if (sf->filebuffer != NULL) + free ((char *)sf->filebuffer); + + if( close(sf->fd) ) { + return( -1 ) ; + } + + free ( sf ); + sf = (SpecFile *)NULL; + + return ( 0 ); +} + + +/********************************************************************* + * + * Function: short SfUpdate( sf, error ) + * + * Description: Updates connection to Spec data file . + * Appends to index list in memory. + * + * Parameters: + * Input : + * (1) sf (pointer to the index list in memory) + * Output: + * (2) error number + * Returns: + * ( 0 ) => Nothing done. + * ( 1 ) => File was updated + * + * Possible errors: + * SF_ERR_FILE_OPEN + * SF_ERR_MEMORY_ALLOC + * + *********************************************************************/ +DllExport short +SfUpdate ( SpecFile *sf, int *error ) +{ + struct stat mystat; + long mtime; + /*printf("In SfUpdate\n"); + __asm("int3");*/ + stat(sf->sfname,&mystat); + + mtime = mystat.st_mtime; + + if (sf->m_time != mtime) { + sfResumeRead (sf,&(sf->cursor),error); + sfReadFile (sf,&(sf->cursor),error); + + sf->m_time = mtime; + sfAssignScanNumbers(sf); +#ifdef SPECFILE_USE_INDEX_FILE + sfWriteIndex (sf,&(sf->cursor),error); +#endif + return(1); + }else{ + return(0); + } +} + + +/********************************************************************* + * + * Function: char *SfError( code ) + * + * Description: Returns the message associated with error 'code'. + * + * Parameters: + * Input : error code + * + *********************************************************************/ +DllExport char * +SfError(int code ) { + int i; + + for ( i=0 ; errors[i].code!=0 ; i++ ) { + if ( errors[i].code == code ) break; + } + return( errors[i].message ); +} + + +static void +sfReadFile(SpecFile *sf,SfCursor *cursor,int *error) { + + int fd; + + char *buffer,*ptr; + + long size,bytesread; + + short status; + + fd = sf->fd; + + size = 1024*1024; + + + if ( (buffer = (char *) malloc(size)) == NULL ) { + /* + * Try smaller buffer + */ + size = 128 * 128; + if ( (buffer = (char *) malloc(size)) == NULL ) { + /* + * Uhmmm + */ + *error = SF_ERR_MEMORY_ALLOC; + free(sf->sfname); + free(sf); + sf = (SpecFile *)NULL; + return; + } + } + + status = NEWLINE; + while ((bytesread = read(fd,buffer,size)) > 0 ) { + + sfStartBuffer(sf,cursor,status,buffer[0],buffer[1],error); + + cursor->bytecnt++; + for (ptr=buffer+1;ptr < buffer + bytesread -1; ptr++,cursor->bytecnt++) { + if (*(ptr-1) == '\n' ) { + sfNewLine(sf,cursor,*ptr,*(ptr+1),error); + } + } + + cursor->bytecnt++; + status = statusEnd(buffer[bytesread-2],buffer[bytesread-1]); + } + + free(buffer); + + sf->no_scans = cursor->scanno; + if (sf->no_scans > 0) { + /* + * Save last + */ + sfSaveScan(sf,cursor,error); + } + return; + +} + + +static void +sfResumeRead ( SpecFile *sf, SfCursor *cursor, int *error) { + cursor->bytecnt = cursor->cursor; + cursor->what = 0; + cursor->hdafoffset = -1; + cursor->dataoffset = -1; + cursor->mcaspectra = 0; + cursor->data = 0; + cursor->scanno--; + sf->updating = 1; + lseek(sf->fd,cursor->bytecnt,SEEK_SET); + return; +} + + +#ifdef SPECFILE_USE_INDEX_FILE +static short +sfOpenIndex ( SpecFile *sf, SfCursor *cursor, int *error) { + char *idxname; + short namelength; + int sfi; + + namelength = strlen(sf->sfname) + strlen(SF_ISFX) + 1; + + idxname = (char *)malloc(sizeof(char) * namelength); + + sprintf(idxname,"%s%s",sf->sfname,SF_ISFX); + + if ((sfi = open(idxname,SF_OPENFLAG)) == -1) { + free(idxname); + return(SF_INIT); + } else { + free(idxname); + return(sfReadIndex(sfi,sf,cursor,error)); + } +} + + +static short +sfReadIndex ( int sfi, SpecFile *sf, SfCursor *cursor, int *error) { + SfCursor filecurs; + char buffer[200]; + long bytesread,i=0; + SpecScan scan; + short modif = 0; + long mtime; + + /* + * read signature + */ + bytesread = read(sfi,buffer,sizeof(SF_SIGNATURE)); + if (strcmp(buffer,SF_SIGNATURE) || bytesread == 0 ) { + return(SF_INIT); + } + + /* + * read cursor and specfile structure + */ + if ( read(sfi,&mtime, sizeof(long)) == 0) return(SF_INIT); + if ( read(sfi,&filecurs, sizeof(SfCursor)) == 0) return(SF_INIT); + + if (sf->m_time != mtime) modif = 1; + + while(read(sfi,&scan, sizeof(SpecScan))) { + addToList(&(sf->list), (void *)&scan, (long)sizeof(SpecScan)); + i++; + } + sf->no_scans = i; + + memcpy(cursor,&filecurs,sizeof(SfCursor)); + + if (modif) return(SF_MODIFIED); + + return(SF_READY); +} + + +static void +sfWriteIndex ( SpecFile *sf, SfCursor *cursor, int *error) { + + int fdi; + char *idxname; + short namelength; + ObjectList *obj; + long mtime; + + namelength = strlen(sf->sfname) + strlen(SF_ISFX) + 1; + + idxname = (char *)malloc(sizeof(char) * namelength); + + sprintf(idxname,"%s%s",sf->sfname,SF_ISFX); + + /* if ((fdi = open(idxname,SF_WRITEFLAG,SF_UMASK)) == -1) { */ + if ((fdi = open(idxname,O_CREAT | O_WRONLY,SF_UMASK)) == -1) { + printf(" - cannot open. Error: (%d)\n",errno); + free(idxname); + return; + } else { + mtime = sf->m_time; + write(fdi,SF_SIGNATURE,sizeof(SF_SIGNATURE)); + /* + * Swap bytes for linux + */ + write(fdi, (void *) &mtime, sizeof(long)); + write(fdi, (void *) cursor, sizeof(SfCursor)); + for( obj = sf->list.first; obj ; obj = obj->next) + write(fdi,(void *) obj->contents, sizeof(SpecScan)); + close(fdi); + free(idxname); + return; + } +} +#endif + + +/***************************************************************************** + * + * Function: static void sfStartBuffer() + * + * Description: start analyzing file buffer and takes into account the last + * bytes of previous reading as defined in variable status + * + *****************************************************************************/ +static void +sfStartBuffer(SpecFile *sf,SfCursor *cursor,short status,char c0,char c1,int *error) { + + if ( status == ANY ) { + return; + } else if ( status == NEWLINE ) { + sfNewLine(sf,cursor,c0,c1,error); + } else if ( status == COMMENT ) { + cursor->bytecnt--; + sfHeaderLine(sf,cursor,c0,error); + cursor->bytecnt++; + } + +} + + +/******************************************************************************* + * + * Function: static void statusEnd() + * + * Description: ends analysis of file buffer and returns a variable + * indicating staus ( last character is COMMENT,NEWLINE of ANY ) + * + *******************************************************************************/ +static short +statusEnd(char c2,char c1) { + + if (c2=='\n' && c1=='#') { + return(COMMENT); + } else if (c1=='\n') { + return(NEWLINE); + } else { + return(ANY); + } +} + + +static void +sfNewLine(SpecFile *sf,SfCursor *cursor,char c0,char c1,int *error) { + if (c0 == '#') { + sfHeaderLine(sf,cursor,c1,error); + } else if (c0 == '@') { + if ( cursor->data == 0 ) { + cursor->dataoffset = cursor->bytecnt; + cursor->data = 1; + } + cursor->mcaspectra++; + } else if ( isdigit(c0) || c0 == '-' || c0 == '+' || c0 == ' ' || c0 == '\t') { + if ( cursor->data == 0 ) { + cursor->dataoffset = cursor->bytecnt; + cursor->data = 1; + } + } +} + + +static void +sfHeaderLine(SpecFile *sf,SfCursor *cursor,char c,int *error) { + if ( c == 'S') { + sfNewBlock(sf,cursor,SCAN,error); + } else if ( c == 'F') { + sfNewBlock(sf,cursor,FILE_HEADER,error); + } else { + if (cursor->data && cursor->hdafoffset == -1 ) + cursor->hdafoffset = cursor->bytecnt; + } +} + + +static void +sfNewBlock(SpecFile *sf,SfCursor *cursor,short newblock,int *error) { + + /* + * Dispatch opened block + */ + if (cursor->what == SCAN) { + sfSaveScan(sf,cursor,error); + } else if ( cursor->what == FILE_HEADER) { + cursor->fileh_size = cursor->bytecnt - cursor->cursor + 1; + } + + /* + * Open new block + */ + if (newblock == SCAN) { + cursor->scanno++; + cursor->what = SCAN; + } else { + cursor->file_header = cursor->bytecnt; + } + cursor->what = newblock; + cursor->hdafoffset = -1; + cursor->dataoffset = -1; + cursor->mcaspectra = 0; + cursor->data = 0; + cursor->cursor = cursor->bytecnt; +} + + +static void +sfSaveScan(SpecFile *sf, SfCursor *cursor,int *error) { + SpecScan scan; + SpecScan *oldscan; + register ObjectList *ptr; + + + scan.index = cursor->scanno; + scan.offset = cursor->cursor; + scan.size = cursor->bytecnt - cursor->cursor; + scan.last = cursor->bytecnt - 1; + scan.data_offset = cursor->dataoffset; + scan.hdafter_offset = cursor->hdafoffset; + scan.mcaspectra = cursor->mcaspectra; + scan.file_header = cursor->file_header; + + if(sf->updating == 1){ + ptr = sf->list.last; + oldscan=(SpecScan *)(ptr->contents); + oldscan->index=scan.index; + oldscan->offset=scan.offset; + oldscan->size=scan.size; + oldscan->last=scan.last; + oldscan->data_offset=scan.data_offset; + oldscan->hdafter_offset=scan.hdafter_offset; + oldscan->mcaspectra=scan.mcaspectra; + oldscan->file_header=scan.file_header; + sf->updating=0; + }else{ + addToList( &(sf->list), (void *)&scan, (long) sizeof(SpecScan)); + } +} + + +static void +sfAssignScanNumbers(SpecFile *sf) { + + int i; + char *ptr; + char buffer[50]; + char buffer2[50]; + + register ObjectList *object, + *object2; + SpecScan *scan, + *scan2; + + for ( object = (sf->list).first; object; object=object->next) { + scan = (SpecScan *) object->contents; + + lseek(sf->fd,scan->offset,SEEK_SET); + read(sf->fd,buffer,sizeof(buffer)); + buffer[49] = '\0'; + + for ( ptr = buffer+3,i=0; *ptr != ' ';ptr++,i++) buffer2[i] = *ptr; + + buffer2[i] = '\0'; + + scan->scan_no = atol(buffer2); + scan->order = 1; + for ( object2 = (sf->list).first; object2 != object; object2=object2->next) { + scan2 = (SpecScan *) object2->contents; + if (scan2->scan_no == scan->scan_no) scan->order++; + } + } +} + +void +printCursor(SfCursor *cursor) { + printf("<Cursor>\n"); + printf(" - Bytecnt: %ld\n",cursor->bytecnt); + printf(" - Cursor: %ld\n",cursor->cursor); + printf(" - Scanno: %ld\n",cursor->scanno); +} diff --git a/src/silx/io/specfile/src/sflabel.c b/src/silx/io/specfile/src/sflabel.c new file mode 100644 index 0000000..61cbb3f --- /dev/null +++ b/src/silx/io/specfile/src/sflabel.c @@ -0,0 +1,654 @@ +# /*########################################################################## +# Copyright (C) 1995-2019 European Synchrotron Radiation Facility +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# +# ############################################################################*/ +/************************************************************************ + * + * File: sflabel.c + * + * Project: SpecFile library + * + * Description: Access to labels and motors + * + * Author: V.Rey + * + * Date: $Date: 2003/02/03 13:15:35 $ + * + ************************************************************************/ +/* + * Log: + * $Log: sflabel.c,v $ + * Revision 1.3 2003/02/03 13:15:35 rey + * Small change in handling of empty spaces at the beginning of the label buffer + * + * Revision 1.2 2002/11/20 09:56:31 sole + * Some macros leave more than 1 space between #L and the first label. + * Routine modified to be able to deal with already collected data. + * The offending macro(s) should be re-written. + * + * Revision 1.1 2002/11/20 08:21:34 sole + * Initial revision + * + * Revision 3.0 2000/12/20 14:17:19 rey + * Python version available + * + * Revision 2.2 2000/12/20 12:12:08 rey + * bug corrected with SfAllMotors + * + * Revision 2.1 2000/07/31 19:05:10 19:05:10 rey (Vicente Rey-Bakaikoa) + * SfUpdate and bug corrected in ReadIndex + * + * Revision 2.0 2000/04/13 13:28:54 13:28:54 rey (Vicente Rey-Bakaikoa) + * New version of the library. Complete rewrite + * Adds support for MCA + */ +#include <SpecFile.h> +#include <SpecFileP.h> +#include <locale_management.h> +#ifndef _GNU_SOURCE +#ifdef PYMCA_POSIX +#include <locale.h> +#endif +#endif + +/* + * Declarations + */ +DllExport char * SfLabel ( SpecFile *sf, long index, long column, + int *error ); +DllExport long SfAllLabels ( SpecFile *sf, long index, char ***labels, + int *error ); +DllExport char * SfMotor ( SpecFile *sf, long index, long number, + int *error ); +DllExport long SfAllMotors ( SpecFile *sf, long index, char ***names, + int *error ); +DllExport double SfMotorPos ( SpecFile *sf, long index, long number, + int *error ); +DllExport double SfMotorPosByName( SpecFile *sf, long index, char *name, + int *error ); +DllExport long SfAllMotorPos ( SpecFile *sf, long index, double **pos, + int *error ); + + +/********************************************************************* + * Function: char *SfLabel( sf, index, column, error ) + * + * Description: Reads one label. + * + * Parameters: + * Input : (1) SpecScan pointer + * (2) Scan index + * (3) Column number + * Output: (4) Error number + * Returns: + * Pointer to the label , + * or NULL if errors occured. + * Possible errors: + * SF_ERR_MEMORY_ALLOC | => getStrFromArr() + * SF_ERR_LABEL_NOT_FOUND + * SF_ERR_LINE_EMPTY | + * SF_ERR_LINE_NOT_FOUND | + * SF_ERR_SCAN_NOT_FOUND | => SfAllLabels() + * SF_ERR_FILE_READ | + * + * Remark: The memory allocated should be freed by the application + * + *********************************************************************/ +DllExport char * +SfLabel( SpecFile *sf, long index, long column, int *error ) +{ + + char **labels=NULL; + long no_labels; + char *label=NULL; + long selection; + + if (sfSetCurrent(sf,index,error) == -1) + return((char *)NULL); + + if (sf->no_labels != -1 ) { + no_labels = sf->no_labels; + } else { + no_labels = SfAllLabels(sf,index,&labels,error); + } + + if (no_labels == 0 || no_labels == -1) return((char *)NULL); + + if ( column < 0 ) { + selection = no_labels + column; + } else { + selection = column - 1; + } + + if (selection < 0 || selection > no_labels - 1 ) { + *error = SF_ERR_COL_NOT_FOUND; + if (labels != (char **) NULL ) + freeArrNZ((void ***)&labels,no_labels); + return((char *)NULL); + } + + if (labels != (char **)NULL) { + label = (char *)strdup(labels[selection]); + freeArrNZ((void ***)&labels,no_labels); + } else { + label = (char *) strdup(sf->labels[selection]); + } + return( label ); +} + + +/********************************************************************* + * Function: long SfAllLabels( sf, index, labels, error ) + * + * Description: Reads all labels in #L lines + * + * Parameters: + * Input : (1) SpecScan pointer + * (2) Scan index + * Output: (3) Labels + * (4) Error number + * Returns: + * Number of labels + * ( -1 ) if error. + * Possible errors: + * SF_ERR_MEMORY_ALLOC ||=> cpyStrArr(),lines2words() + * SF_ERR_SCAN_NOT_FOUND | => SfHeader() + * SF_ERR_FILE_READ | + * SF_ERR_LINE_EMPTY + * SF_ERR_LINE_NOT_FOUND + * Remark: The memory allocated should be freed by the application + * + *********************************************************************/ +DllExport long +SfAllLabels( SpecFile *sf, long index, char ***labels, int *error ) +{ + static char tmplab[40]; + + char **labarr; + char *onelabel; + + char *ptr, + *buf=NULL; + + long no_labels = 0; + short i; + + /* + * select scan + */ + if (sfSetCurrent(sf,index,error) == -1) { + *labels = NULL; + return(0); + } + + /* + * Do not do it if already done + */ + if (sf->labels != (char **)NULL ) { + labarr = (char **)malloc(sizeof(char *) * sf->no_labels); + for ( i=0;i<sf->no_labels;i++) + labarr[i] = (char *)strdup(sf->labels[i]); + *labels = labarr; + return(sf->no_labels); + } + + /* + * else.. + */ + if (sfGetHeaderLine(sf,FROM_SCAN,SF_LABEL,&buf,error) == -1) { + *labels = NULL; + return(0); + } + + if ( buf[0] == '\0') { + *labels = NULL; + return(0); + } + + if ( (labarr = (char **)malloc( sizeof(char *))) == (char **)NULL) { + *error = SF_ERR_MEMORY_ALLOC; + return(-1); + } + + no_labels = 0; + i = 0; + + /* + * avoid problem of having too many spaces at the beginning + * with bad written macros -> added check for empty string + * + * get rid of spaces at the beginning of the string buffer + */ + + ptr = buf; + while((ptr < buf + strlen(buf) -1) && (*ptr == ' ')) ptr++; + + for (i=0;ptr < buf + strlen(buf) -1;ptr++,i++) { + if (*ptr==' ' && *(ptr+1) == ' ') { /* two spaces delimits one label */ + tmplab[i] = '\0'; + + labarr = (char **)realloc( labarr, (no_labels+1) * sizeof(char *)); + onelabel = (char *) malloc (i+2); + strcpy(onelabel,tmplab); + labarr[no_labels] = onelabel; + + no_labels++; + i=-1; + for(;*(ptr+1) == ' ' && ptr < buf+strlen(buf)-1;ptr++); + } else { + tmplab[i] = *ptr; + } + } + + if (*ptr != ' ') { + tmplab[i] = *ptr; + i++; + } + tmplab[i] = '\0'; + + labarr = (char **)realloc( labarr, (no_labels+1) * sizeof(char *)); + onelabel = (char *) malloc (i+2); + strcpy(onelabel,tmplab); + labarr[no_labels] = onelabel; + + no_labels++; + + /* + * Save in specfile structure + */ + sf->no_labels = no_labels; + sf->labels = (char **) malloc( sizeof(char *) * no_labels); + for (i=0;i<no_labels;i++) + sf->labels[i] = (char *) strdup(labarr[i]); + + *labels = labarr; + return( no_labels ); +} + + +/********************************************************************* + * Function: long SfAllMotors( sf, index, names, error ) + * + * Description: Reads all motor names in #O lines (in file header) + * + * Parameters: + * Input : (1) SpecScan pointer + * (2) Scan index + * Output: (3) Names + * (4) Error number + * Returns: + * Number of found names + * ( -1 ) if errors. + * Possible errors: + * SF_ERR_SCAN_NOT_FOUND + * SF_ERR_LINE_NOT_FOUND + * SF_ERR_LINE_EMPTY + * SF_ERR_MEMORY_ALLOC || => cpyStrArr(),lines2words() + * SF_ERR_FILE_READ | + * SF_ERR_HEADER_NOT_FOUND | => SfFileHeader() + * + * Remark: The memory allocated should be freed by the application + * + *********************************************************************/ +DllExport long +SfAllMotors( SpecFile *sf, long index, char ***names, int *error ) +{ + char **lines; + char *thisline, + *endline; + + char **motarr; + char *onemot; + + static char tmpmot[40]; + + char *ptr; + + long motct = 0; + long no_lines; + short i,j; + + /* + * go to scan + */ + if (sfSetCurrent(sf,index,error) == -1) { + *names = NULL; + return(0); + } + + /* + * if motor names for this scan have already been read + */ + if (sf->motor_names != (char **)NULL) { + motarr = (char **)malloc(sizeof(char *) * sf->no_motor_names); + for (i=0;i<sf->no_motor_names;i++) { + motarr[i] = (char *) strdup (sf->motor_names[i]); + } + *names = motarr; + return(sf->no_motor_names); + } + + /* + * else + */ + no_lines = SfHeader(sf, index,"O",&lines,error); + if (no_lines == -1 || no_lines == 0 ) { + *names = (char **) NULL; + return(-1); + } + + if ( (motarr = (char **)malloc( sizeof(char *))) == (char **)NULL) { + *error = SF_ERR_MEMORY_ALLOC; + return(-1); + } + + motct = 0; + + for (j=0;j<no_lines;j++) { + thisline = lines[j] + 4; + endline = thisline + strlen(thisline); + for(ptr=thisline;*ptr == ' ';ptr++); + for (i=0;ptr < endline -2;ptr++,i++) { + if (*ptr==' ' && *(ptr+1) == ' ') { + tmpmot[i] = '\0'; + + motarr = (char **)realloc( motarr, (motct+1) * sizeof(char *)); + onemot = (char *) malloc (i+2); + strcpy(onemot,tmpmot); + motarr[motct] = onemot; + + motct++; + i=-1; + for(;*(ptr+1) == ' ' && ptr < endline -1;ptr++); + } else { + tmpmot[i] = *ptr; + } + } + if (*ptr != ' ') { tmpmot[i] = *ptr; i++; } + ptr++; + if (*ptr != ' ') { tmpmot[i] = *ptr; i++; } + + tmpmot[i] = '\0'; + motarr = (char **)realloc( motarr, (motct+1) * sizeof(char *)); + + onemot = (char *) malloc (i+2); + strcpy(onemot,tmpmot); + motarr[motct] = onemot; + + motct++; + + } + + /* + * Save in specfile structure + */ + sf->no_motor_names = motct; + sf->motor_names = (char **)malloc(sizeof(char *) * motct); + for (i=0;i<motct;i++) { + sf->motor_names[i] = (char *)strdup(motarr[i]); + } + + *names = motarr; + return( motct ); + +} + + +DllExport char * +SfMotor( SpecFile *sf, long index, long motnum, int *error ) +{ + + char **motors=NULL; + long nb_mot; + char *motor=NULL; + long selection; + + /* + * go to scan + */ + if (sfSetCurrent(sf,index,error) == -1) { + return((char *)NULL); + } + + if ( sf->no_motor_names != -1 ) { + nb_mot = sf->no_motor_names; + } else { + nb_mot = SfAllMotors(sf,index,&motors,error); + } + + if (nb_mot == 0 || nb_mot == -1) return((char *)NULL); + + if ( motnum < 0 ) { + selection = nb_mot + motnum; + } else { + selection = motnum - 1; + } + + if (selection < 0 || selection > nb_mot - 1 ) { + *error = SF_ERR_COL_NOT_FOUND; + if (motors != (char **) NULL) + freeArrNZ((void ***)&motors,nb_mot); + return((char *)NULL); + } + + if (motors != (char **) NULL) { + motor = (char *)strdup(motors[selection]); + freeArrNZ((void ***)&motors,nb_mot); + } else { + motor = (char *)strdup(sf->motor_names[selection]); + } + return( motor ); +} + + +DllExport long +SfAllMotorPos ( SpecFile *sf, long index, double **retpos, int *error ) +{ + char **lines; + char *thisline, + *endline; + + double *posarr; + + static double pos[300]; + static char posstr[40]; + + char *ptr; + + long motct = 0; + long no_lines; + short i,j; + +#ifndef _GNU_SOURCE +#ifdef PYMCA_POSIX + char *currentLocaleBuffer; + char localeBuffer[21]; +#endif +#endif + + if (sfSetCurrent(sf,index,error) == -1) { + *retpos = (double *) NULL; + return(0); + } + + /* + * if motors position for this scan have already been read + */ + if (sf->motor_pos != (double *)NULL) { + posarr = (double *)malloc(sizeof(double) * sf->no_motor_pos); + for (i=0;i<sf->no_motor_pos;i++) { + posarr[i] = sf->motor_pos[i]; + } + *retpos = posarr; + return(sf->no_motor_pos); + } + + /* + * else + */ + no_lines = SfHeader(sf, index,"P",&lines,error); + + if (no_lines == -1 || no_lines == 0 ) { + *retpos = (double *) NULL; + return(-1); + } + + motct = 0; +#ifndef _GNU_SOURCE +#ifdef PYMCA_POSIX + currentLocaleBuffer = setlocale(LC_NUMERIC, NULL); + strcpy(localeBuffer, currentLocaleBuffer); + setlocale(LC_NUMERIC, "C\0"); +#endif +#endif + for (j=0;j<no_lines;j++) { + thisline = lines[j] + 4; + endline = thisline + strlen(thisline); + for(ptr=thisline;*ptr == ' ';ptr++); + for (i=0;ptr < endline -1;ptr++,i++) { + if (*ptr==' ') { + posstr[i] = '\0'; + + pos[motct] = PyMcaAtof(posstr); + + motct++; + i=-1; + for(;*(ptr+1) == ' ' && ptr < endline -1;ptr++); + } else { + posstr[i] = *ptr; + } + } + if (*ptr != ' ') { + posstr[i] = *ptr; + i++; + } + posstr[i] = '\0'; + pos[motct] = PyMcaAtof(posstr); + + motct++; + + } + +#ifndef _GNU_SOURCE +#ifdef PYMCA_POSIX + setlocale(LC_NUMERIC, localeBuffer); +#endif +#endif + + /* + * Save in specfile structure + */ + sf->no_motor_pos = motct; + sf->motor_pos = (double *)malloc(sizeof(double) * motct); + memcpy(sf->motor_pos,pos,motct * sizeof(double)); + + /* + * and return + */ + posarr = (double *) malloc ( sizeof(double) * motct ) ; + memcpy(posarr,pos,motct * sizeof(double)); + + *retpos = posarr; + + return( motct ); +} + + +DllExport double +SfMotorPos( SpecFile *sf, long index, long motnum, int *error ) +{ + + double *motorpos=NULL; + long nb_mot; + double retpos; + long selection; + + if (sfSetCurrent(sf,index,error) == -1) + return(HUGE_VAL); + + if (sf->no_motor_pos != -1 ) { + nb_mot = sf->no_motor_pos; + } else { + nb_mot = SfAllMotorPos(sf,index,&motorpos,error); + } + + if (nb_mot == 0 || nb_mot == -1) return(HUGE_VAL); + + if ( motnum < 0 ) { + selection = nb_mot + motnum; + } else { + selection = motnum - 1; + } + + if (selection < 0 || selection > nb_mot - 1 ) { + *error = SF_ERR_COL_NOT_FOUND; + if (motorpos != (double *)NULL) + free(motorpos); + return(HUGE_VAL); + } + + if (motorpos != (double *)NULL) { + retpos = motorpos[selection]; + free(motorpos); + } else { + retpos = sf->motor_pos[selection]; + } + return( retpos ); +} + + +DllExport double +SfMotorPosByName( SpecFile *sf, long index, char *name, int *error ) +{ + char **motors=NULL; + + long nb_mot, + idx, + selection; + short tofree=0; + + if (sfSetCurrent(sf,index,error) == -1) + return(HUGE_VAL); + + if ( sf->no_motor_names != -1 ) { + nb_mot = sf->no_motor_names; + motors = sf->motor_names; + } else { + nb_mot = SfAllMotors(sf,index,&motors,error); + tofree=1; + } + + if (nb_mot == 0 || nb_mot == -1) return(HUGE_VAL); + + for (idx = 0;idx<nb_mot;idx++) { + if (!strcmp(name,motors[idx])) break; + } + + if (idx == nb_mot) { + if (tofree) freeArrNZ((void ***)&motors,nb_mot); + *error = SF_ERR_MOTOR_NOT_FOUND; + return(HUGE_VAL); + } + + selection = idx+1; + + return(SfMotorPos(sf,index,selection,error)); +} diff --git a/src/silx/io/specfile/src/sflists.c b/src/silx/io/specfile/src/sflists.c new file mode 100644 index 0000000..aca267f --- /dev/null +++ b/src/silx/io/specfile/src/sflists.c @@ -0,0 +1,189 @@ +# /*########################################################################## +# Copyright (C) 1995-2017 European Synchrotron Radiation Facility +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# +# ############################################################################*/ +/************************************************************************ + * + * File: sflists.c + * + * Project: SpecFile library + * + * Description: Functions to handle lists + * + * Author: V.Rey + * + * Date: $Date: 2003/03/06 17:00:42 $ + * + ************************************************************************/ +/* + * Log: $Log: sflists.c,v $ + * Log: Revision 1.1 2003/03/06 17:00:42 sole + * Log: Initial revision + * Log: + * Log: Revision 3.0 2000/12/20 14:17:19 rey + * Log: Python version available + * Log: + * Revision 2.1 2000/07/31 19:03:25 19:03:25 rey (Vicente Rey-Bakaikoa) + * SfUpdate and bug corrected in ReadIndex + * + * Revision 2.0 2000/04/13 13:28:54 13:28:54 rey (Vicente Rey-Bakaikoa) + * New version of the library. Complete rewrite + * Adds support for MCA + */ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <Lists.h> + +/* + * Function declaration + */ +ObjectList * findInList ( ListHeader *list, int (*proc)(void *,void *), void *value ); +long addToList ( ListHeader *list, void *object, long size ); +void unlinkFromList ( ListHeader *list, ObjectList *element ); + +static long linkToList ( ListHeader *list, void *object ); + + +/********************************************************************* + * Function: ObjectList *findInList( list, proc, value ) + * + * Description: Looks for an list element. + * + * Parameters: + * Input : (1) ListHeader pointer + * (2) Comp. procedure + * (3) value + * Returns: + * Pointer to the found element , + * NULL if not found . + * + *********************************************************************/ +ObjectList * +findInList( ListHeader *list, int (*proc)(void * , void *), void *value ) +{ + register ObjectList *ptr; + + for ( ptr=list->first ; ptr ; ptr=ptr->next ) { + if ( (*proc)(ptr->contents, value) ) { + return( ptr ); + } + } + return (ObjectList *)NULL; +} + + +/********************************************************************* + * Function: int addToList( list, object, size ) + * + * Description: Adds an element to the list. + * + * Parameters: + * Input : (1) List pointer + * (2) Pointer to the new element + * (3) Size of the new element + * Returns: + * ( 0 ) => OK + * ( -1 ) => error + * + *********************************************************************/ +long +addToList( ListHeader *list, void *object, long size ) +{ + void *newobj; + + if ( (newobj = (void *)malloc(size)) == (void *)NULL ) return( -1 ); + memcpy(newobj, object, size); + + return( linkToList( list, newobj ) ); + +} + + +/********************************************************************* + * Function: int linkToList( list, object ) + * + * Description: Adds an element to the list. + * + * Parameters: + * Input: (1) ListHeader pointer + * (2) pointer to the new element + * Returns: + * ( 0 ) => OK + * ( -1 ) => error + * + *********************************************************************/ +static long +linkToList( ListHeader *list, void *object ) +{ + ObjectList *newobj; + + + if ((newobj = (ObjectList *) malloc(sizeof(ObjectList))) == + (ObjectList *) NULL) return( -1 ); + + newobj->contents = object; + newobj->prev = list->last; + newobj->next = NULL; + + if (list->first == (ObjectList *)NULL) { + list->first = newobj; + } else { + (list->last)->next = newobj; + } + + list->last = newobj; + return( 0 ); +} + + +/********************************************************************* + * Function: int unlinkFromList( list, element ) + * + * Description: Removes an element from the list. + * + * Parameters: + * Input : (1) List pointer + * (2) Pointer to the element + * + *********************************************************************/ +void +unlinkFromList( ListHeader *list, ObjectList *element ) +{ + + if ( element != (ObjectList *)NULL ) { + if ( element->next != (ObjectList *)NULL ) { + element->next->prev = element->prev; + } + else { + list->last = element->prev ; + } + if ( element->prev != (ObjectList *)NULL ) { + element->prev->next = element->next; + } + else { + list->first = element->next; + } + free( element->contents ); + free( element ); + } +} + diff --git a/src/silx/io/specfile/src/sfmca.c b/src/silx/io/specfile/src/sfmca.c new file mode 100644 index 0000000..ad13bae --- /dev/null +++ b/src/silx/io/specfile/src/sfmca.c @@ -0,0 +1,341 @@ +# /*########################################################################## +# Copyright (C) 2000-2017 European Synchrotron Radiation Facility +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# +# ############################################################################*/ +/************************************************************************ + * + * File: sfmca.c + * + * Project: SpecFile library + * + * Description: Access to MCA spectra + * + * Author: V.Rey + * + * Date: $Date: 2002/11/15 16:25:44 $ + * + ************************************************************************/ +/* + * Log: $Log: sfmca.c,v $ + * Log: Revision 1.3 2002/11/15 16:25:44 sole + * Log: free(retline) replaced by freeArrNZ((void ***) &retline,nb_lines); to eliminate the memory leak when reading mca + * Log: + * Log: Revision 1.2 2002/11/15 10:44:36 sole + * Log: added free(retline) after call to SfHeader + * Log: + * Log: Revision 1.1 2002/11/15 10:17:38 sole + * Log: Initial revision + * Log: + * Log: Revision 3.0 2000/12/20 14:17:19 rey + * Log: Python version available + * Log: + * Revision 2.1 2000/07/31 19:05:12 19:05:12 rey (Vicente Rey-Bakaikoa) + * SfUpdate and bug corrected in ReadIndex + * + * Revision 2.0 2000/04/13 13:28:54 13:28:54 rey (Vicente Rey-Bakaikoa) + * New version of the library. Complete rewrite + * Adds support for MCA + */ +#include <SpecFile.h> +#include <SpecFileP.h> +#include <locale_management.h> +#ifndef _GNU_SOURCE +#ifdef PYMCA_POSIX +#include <locale.h> +#endif +#endif + +#include <ctype.h> +#include <stdlib.h> +/* + * Define macro + */ +#define isnumber(this) ( isdigit(this) || this == '-' || this == '+' || this =='e' || this == 'E' || this == '.' ) + +/* + * Mca continuation character + */ +#define MCA_CONT '\\' +#define D_INFO 3 + +/* + * Declarations + */ +DllExport long SfNoMca ( SpecFile *sf, long index, int *error ); +DllExport int SfGetMca ( SpecFile *sf, long index, long mcano, + double **retdata, int *error ); +DllExport long SfMcaCalib ( SpecFile *sf, long index, double **calib, + int *error ); + + +/********************************************************************* + * Function: long SfNoMca( sf, index, error ) + * + * Description: Gets number of mca spectra in a scan + * + * Parameters: + * Input : (1) File pointer + * (2) Index + * Output: + * (3) error number + * Returns: + * Number of data lines , + * ( -1 ) => errors. + * Possible errors: + * SF_ERR_SCAN_NOT_FOUND + * + *********************************************************************/ +DllExport long +SfNoMca( SpecFile *sf, long index, int *error ) +{ + + if (sfSetCurrent(sf,index,error) == -1 ) + return(-1); + + return( ((SpecScan *)sf->current->contents)->mcaspectra ); + +} + + +/********************************************************************* + * Function: int SfGetMca(sf, index, number, data, error) + * + * Description: Gets data. + * Parameters: + * Input : (1) File pointer + * (2) Index + * Output: + * (3) Data array + * (4) Data info : [0] => no_lines + * [1] => no_columns + * [2] = ( 0 ) => regular + * ( 1 ) => not regular ! + * (5) error number + * Returns: + * ( 0 ) => OK + * ( -1 ) => errors occured + * Possible errors: + * SF_ERR_MEMORY_ALLOC + * SF_ERR_FILE_READ + * SF_ERR_SCAN_NOT_FOUND + * SF_ERR_LINE_NOT_FOUND + * + * Remark: The memory allocated should be freed by the application + * + *********************************************************************/ +DllExport int +SfGetMca( SpecFile *sf, long index, long number, double **retdata, int *error ) +{ + double *data = NULL; + long headersize; + int old_fashion; + static char* last_from = NULL; + static char* last_pos = NULL; + static long last_number = 0; + long int scanno = 0; + static long int last_scanno = 0; + char *ptr, + *from, + *to; + + char strval[100]; + double val; + + int i,spect_no=0; + long vals; + + long blocks=1, + initsize=1024; +#ifndef _GNU_SOURCE +#ifdef PYMCA_POSIX + char *currentLocaleBuffer; + char localeBuffer[21]; +#endif +#endif + + headersize = ((SpecScan *)sf->current->contents)->data_offset + - ((SpecScan *)sf->current->contents)->offset; + + scanno = ((SpecScan *)sf->current->contents)->scan_no; + + /* + * check that mca number is available + */ + if (number < 1) { + *error = SF_ERR_MCA_NOT_FOUND; + *retdata = (double *)NULL; + return(-1); + } + + /* + * Get MCA info from header + */ + + from = sf->scanbuffer + headersize; + to = sf->scanbuffer + ((SpecScan *)sf->current->contents)->size; + + old_fashion = 1; + if (last_scanno == scanno) + { + if (last_from == from) + { + /* same scan as before */ + if (number > last_number) + { + spect_no = last_number; + old_fashion = 0; + } + } + } + if (old_fashion) + { + last_scanno = scanno; + last_from = from; + spect_no = 0; + last_pos = from; + } + /* + * go and find the beginning of spectrum + */ + ptr = last_pos; + + if ( *ptr == '@' ) { + spect_no++; + ptr++; + last_pos = ptr; + } + + while ( spect_no != number && ptr < to ) { + if (*ptr == '@') spect_no++; + ptr++; + last_pos = ptr; + } + ptr++; + + if ( spect_no != number ) { + *error = SF_ERR_MCA_NOT_FOUND; + *retdata = (double *)NULL; + return(-1); + } + last_number = spect_no; + /* + * Calculate size and book memory + */ + initsize = 2048; + + i = 0; + vals = 0; + + /* + * Alloc memory + */ + if ((data = (double *)malloc (sizeof(double) * initsize)) == (double *)NULL) { + *error = SF_ERR_MEMORY_ALLOC; + return(-1); + } + + /* + * continue + */ +#ifndef _GNU_SOURCE +#ifdef PYMCA_POSIX + currentLocaleBuffer = setlocale(LC_NUMERIC, NULL); + strcpy(localeBuffer, currentLocaleBuffer); + setlocale(LC_NUMERIC, "C\0"); +#endif +#endif + for ( ;(*(ptr+1) != '\n' || (*ptr == MCA_CONT)) && ptr < to - 1 ; ptr++) + { + if (*ptr == ' ' || *ptr == '\t' || *ptr == '\\' || *ptr == '\n') { + if ( i ) { + if ( vals%initsize == 0 ) { + blocks++; + if ((data = (double *)realloc (data, sizeof(double) * blocks * initsize)) + == (double *)NULL) { + *error = SF_ERR_MEMORY_ALLOC; +#ifndef _GNU_SOURCE +#ifdef PYMCA_POSIX + setlocale(LC_NUMERIC, localeBuffer); +#endif +#endif + return(-1); + } + + } + strval[i] = '\0'; + i = 0; + val = PyMcaAtof(strval); + data[vals] = val; + vals++; + } + } else if (isnumber(*ptr)) { + strval[i] = *ptr; + i++; + } + } + + if (isnumber(*ptr)) { + strval[i] = *ptr; + strval[i+1] = '\0'; + val = PyMcaAtof(strval); + data[vals] = val; + vals++; + } +#ifndef _GNU_SOURCE +#ifdef PYMCA_POSIX + setlocale(LC_NUMERIC, localeBuffer); +#endif +#endif + + *retdata = data; + + return( vals ); +} + + +DllExport long +SfMcaCalib ( SpecFile *sf, long index, double **calib, int *error ) +{ + + long nb_lines; + char **retline; + char *strptr; + + double val1,val2,val3; + + double *retdata; + + nb_lines = SfHeader(sf,index,"@CALIB",&retline,error); + + if (nb_lines > 0) { + strptr = retline[0] + 8; + sscanf(strptr,"%lf %lf %lf",&val1,&val2,&val3); + } else { + *calib = (double *)NULL; + return(-1); + } + + retdata = (double *) malloc(sizeof(double) * 3 ); + retdata[0] = val1; retdata[1] = val2; retdata[2] = val3; + + *calib = retdata; + return(0); +} diff --git a/src/silx/io/specfile/src/sftools.c b/src/silx/io/specfile/src/sftools.c new file mode 100644 index 0000000..9b78b67 --- /dev/null +++ b/src/silx/io/specfile/src/sftools.c @@ -0,0 +1,554 @@ +# /*########################################################################## +# Copyright (C) 1995-2017 European Synchrotron Radiation Facility +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# +# ############################################################################*/ +/************************************************************************ + * + * File: sftools.c + * + * Project: SpecFile library + * + * Description: General library tools + * + * Author: V.Rey + * + * Date: $Date: 2004/05/12 16:57:02 $ + * + ************************************************************************/ +/* + * Log: $Log: sftools.c,v $ + * Log: Revision 1.2 2004/05/12 16:57:02 sole + * Log: Windows support + * Log: + * Log: Revision 1.1 2003/09/12 10:34:11 sole + * Log: Initial revision + * Log: + * Log: Revision 3.0 2000/12/20 14:17:19 rey + * Log: Python version available + * Log: + * Log: Revision 2.2 2000/12/20 12:12:08 rey + * Log: bug corrected with SfAllMotors + * Log: + * Revision 2.1 2000/07/31 19:05:07 19:05:07 rey (Vicente Rey-Bakaikoa) + * SfUpdate and bug corrected in ReadIndex + * + * Revision 2.0 2000/04/13 13:28:54 13:28:54 rey (Vicente Rey-Bakaikoa) + * New version of the library. Complete rewrite + * Adds support for MCA + */ +#include <SpecFile.h> +#include <SpecFileP.h> + +#ifdef WIN32 +#include <stdio.h> +#include <stdlib.h> +#else +#include <unistd.h> +#endif + +/* + * Library Functions + */ +DllExport void freePtr ( void *ptr ); +DllExport void freeArrNZ ( void ***ptr, long lines ); +DllExport void SfShow (SpecFile *sf); +DllExport void SfShowScan (SpecFile *sf, long index); + +/* + * Function declaration + */ +void freeArr ( void ***ptr, long lines ); + +int sfSetCurrent ( SpecFile *sf, long index, int *error ); +int sfSameFile ( SpecFile *sf, ObjectList *list ); +int sfSameScan ( SpecFile *sf, long index ); + +int findIndex ( void *scan, void *number ); +int findNoAndOr ( void *scan, void *number ); +int findFirst ( void *scan, void *file_offset ); +ObjectList *findScanByIndex ( ListHeader *list, long index ); +ObjectList *findFirstInFile ( ListHeader *list, long file_offset ); +ObjectList *findScanByNo ( ListHeader *list, long scan_no, long order ); + +long mulstrtod ( char *str, double **arr, int *error ); +void freeAllData ( SpecFile *sf ); + +/* + * Globals + */ + + +/********************************************************************* + * Function: void sfSetCurrent( sf, list ) + * + * Description: Sets 'list' to current scan. + * Updates SpecFile structure. + * Parameters: + * Input : (1) SpecFile pointer + * (2) New scan + * + *********************************************************************/ +int +sfSetCurrent( SpecFile *sf, long index,int *error ) +{ + ObjectList *list, + *flist; + SpecScan *scan, + *fscan; + long nbytes; + long fileheadsize,start; + + /* + * If same scan nothing to do + */ + if (sfSameScan(sf,index)) return(0); + + /* + * It is a new scan. Free memory allocated for previous one. + */ + freeAllData(sf); + + /* + * Find scan + */ + list = findScanByIndex(&(sf->list),index); + + if (list == (ObjectList *)NULL) { + *error = SF_ERR_SCAN_NOT_FOUND; + return(-1); + } + + /* + * Read full scan into buffer + */ + scan = list->contents; + + if (sf->scanbuffer != ( char * ) NULL) free(sf->scanbuffer); + + sf->scanbuffer = ( char *) malloc(scan->size); + + if (sf->scanbuffer == (char *)NULL) { + *error = SF_ERR_MEMORY_ALLOC; + return(-1); + } + + lseek(sf->fd,scan->offset,SEEK_SET); + nbytes = read(sf->fd,sf->scanbuffer,scan->size); + if ( nbytes == -1) { + *error = SF_ERR_FILE_READ; + return(-1); + } + if ( sf->scanbuffer[0] != '#' || sf->scanbuffer[1] != 'S') { + *error = SF_ERR_FILE_READ; + return(-1); + } + sf->scanheadersize = scan->data_offset - scan->offset; + + /* + * if different file read fileheader also + */ + if (!sfSameFile(sf,list)) { + if (sf->filebuffer != ( char * ) NULL) free(sf->filebuffer); + + start = scan->file_header; + flist = findFirstInFile(&(sf->list),scan->file_header); + if (flist == (ObjectList *) NULL) { + fileheadsize = 0; + sf->filebuffersize = fileheadsize; + } + else + { + fscan = flist->contents; + fileheadsize = fscan->offset - start; + } + + if (fileheadsize > 0) { + sf->filebuffer = ( char *) malloc(fileheadsize); + if (sf->filebuffer == (char *)NULL) { + *error = SF_ERR_MEMORY_ALLOC; + return(-1); + } + lseek(sf->fd,start,SEEK_SET); + nbytes = read(sf->fd,sf->filebuffer,fileheadsize); + if ( nbytes == -1) { + *error = SF_ERR_FILE_READ; + return(-1); + } + sf->filebuffersize = fileheadsize; + } + } + sf->scansize = scan->size; + sf->current = list; + + return(1); +} + + +/********************************************************************* + * Function: int sfSameFile( sf, list ) + * + * Description: Checks if the current scan file header and + * the new scan file header are the same. + * Parameters: + * Input : (1) SpecFile pointer + * (2) New scan + * Returns: + * 1 - the same + * 0 - not the same + * + *********************************************************************/ +int +sfSameFile( SpecFile *sf, ObjectList *list ) +{ + if (sf->current) { + return ( ((SpecScan *)sf->current->contents)->file_header == + ((SpecScan *)list->contents)->file_header ); + } else return(0); +} + + +/********************************************************************* + * Function: int sfSameScan( sf, index ) + * + * Description: Checks if the current scan and + * the new scan are the same. + * Parameters: + * Input : (1) SpecFile pointer + * (2) New scan index + * Returns: + * 1 - the same + * 0 - not the same + * + *********************************************************************/ +int +sfSameScan( SpecFile *sf, long index ) +{ + if ( sf->current == (ObjectList *)NULL) return(0); + + return ( ((SpecScan *)sf->current->contents)->index == index ); +} + + +/********************************************************************* + * Function: freePtr( ptr ); + * + * Description: Frees memory pointed to by 'ptr'. + * + * Parameters: + * Input : (1) Pointer + * + *********************************************************************/ +void +freePtr( void *ptr ) +{ + free( ptr ); +} + + +/********************************************************************* + * Function: freeArrNZ( ptr, lines ); + * + * Description: Frees an array if 'lines' > zero. + * + * Parameters: + * Input : (1) Array pointer + * (2) No. of lines + * + *********************************************************************/ +void +freeArrNZ( void ***ptr, long lines ) +{ + if ( *ptr != (void **)NULL && lines > 0 ) { + for ( ; lines ; lines-- ) { + free( (*ptr)[lines-1] ); + } + free( *ptr ); + *ptr = ( void **)NULL ; + } +} + + +/********************************************************************* + * Function: freeArr( ptr, lines ); + * + * Description: Frees an array. + * 'ptr' will be always freed !!! + * + * Parameters: + * Input : (1) Array pointer + * (2) No. of lines + * + *********************************************************************/ +void +freeArr( void ***ptr, long lines ) +{ + if ( *ptr != (void **)NULL ) { + if ( lines > 0 ) { + for ( ; lines ; lines-- ) { + free( (*ptr)[lines-1] ); + } + } + free( *ptr ); + *ptr = ( void **)NULL ; + } +} + + +/********************************************************************* + * Function: int findIndex( scan, number ) + * + * Description: Compares if number == scan index . + * + * Parameters: + * Input : (1) SpecScan pointer + * (2) number + * Returns: + * 0 : not found + * 1 : found + * + *********************************************************************/ +int +findIndex( void *scan, void *number ) +{ + return( ((SpecScan *)scan)->index == *(long *)number ); +} + + +/********************************************************************* + * Function: int findFirst( scan, file_offset ) + * + * Description: Compares if scan offset > file_offset + * + * Parameters: + * Input : (1) SpecScan pointer + * (2) number + * Returns: + * 0 : not found + * 1 : found + * + *********************************************************************/ +int +findFirst( void *scan, void *file_offset ) +{ + return( ((SpecScan *)scan)->offset > *(long *)file_offset ); +} + + +/********************************************************************* + * Function: int findNoAndOr( scan, number ) + * ( Number + * Order ) + * + * Description: Compares if number1 = scan number and + * number2 = scan order + * Parameters: + * Input: (1) SpecScan pointer + * (2) number[1] + * Returns: + * 0 : not found + * 1 : found + * + *********************************************************************/ +int +findNoAndOr( void *scan, void *number ) +{ + + long *n = (long *)number; + + return( ( ((SpecScan *)scan)->scan_no == *n++ ) && ( ((SpecScan *)scan)->order == *n )); +} + + +/********************************************************************* + * Function: ObjectList *findScanByIndex( list, index ) + * + * Description: Looks for a scan . + * + * Parameters: + * Input: (1) List pointer + * (2) scan index + * Returns: + * ObjectList pointer if found , + * NULL if not. + * + *********************************************************************/ +ObjectList * +findScanByIndex( ListHeader *list, long index ) +{ + return findInList( list, findIndex, (void *)&index ); +} + + +/********************************************************************* + * Function: ObjectList findScanByNo( list, scan_no, order ) + * + * Description: Looks for a scan . + * + * Parameters: + * Input: (1) List pointer + * (2) scan number + * (3) scan order + * Returns: + * ObjectList pointer if found , + * NULL if not. + * + *********************************************************************/ +ObjectList * +findScanByNo( ListHeader *list, long scan_no, long order ) +{ + long value[2]; + + value[0] = scan_no; + value[1] = order; + + return( findInList( (void *)list, findNoAndOr, (void *)value) ); +} + + + +/********************************************************************* + * Function: ObjectList *findFirstInFile( list, file_offset ) + * + * Description: Looks for a scan . + * + * Parameters: + * Input: (1) List pointer + * (2) scan index + * Returns: + * ObjectList pointer if found , + * NULL if not. + * + *********************************************************************/ +ObjectList * +findFirstInFile( ListHeader *list, long file_offset ) +{ + return findInList( list, findFirst, (void *)&file_offset ); +} + + +/********************************************************************* + * Function: long mulstrtod( str, arr, error ) + * + * Description: Converts string to data array.( double array ) + * + * Parameters: + * Input : (1) String + * + * Output: + * (2) Data array + * (3) error number + * Returns: + * Number of values. + * ( -1 ) in case of errors. + * Possible errors: + * SF_ERR_MEMORY_ALLOC + * + * Remark: The memory allocated should be freed by the application + * + *********************************************************************/ +long +mulstrtod( char *str, double **arr, int *error ) +{ + int count,q,i=0; + double *ret; + char *str2; + static double tmpret[200]; + + *arr = (double *)NULL; + + str2 = str; + + while( (q = sscanf(str2, "%lf%n", &(tmpret[i]), &count)) > 0 ) { + i++; + str2 += count; + } + str2++; + + if ( !i ) { + return( i ); + } + + ret = (double *)malloc( sizeof(double) * i ); + + if ( ret == (double *)NULL ) { + *error = SF_ERR_MEMORY_ALLOC; + return( -1 ); + } + memcpy(ret, tmpret, i * sizeof(double) ); + + *arr = ret; + return( i ); +} + +void +freeAllData(SpecFile *sf) +{ + if (sf->motor_pos != (double *)NULL) { + free(sf->motor_pos); + sf->motor_pos = (double *)NULL; + sf->no_motor_pos = -1; + } + if (sf->motor_names != (char **)NULL) { + freeArrNZ((void ***)&(sf->motor_names),sf->no_motor_names); + sf->motor_names = (char **)NULL; + sf->no_motor_names = -1; + } + if (sf->labels != (char **)NULL) { + freeArrNZ((void ***)&(sf->labels),sf->no_labels); + sf->labels = (char **)NULL; + sf->no_labels = -1; + } + if (sf->data_info != (long *)NULL) { + freeArrNZ((void ***)&(sf->data),sf->data_info[ROW]); + free(sf->data_info); + sf->data = (double **)NULL; + sf->data_info = (long *)NULL; + } +} + +DllExport void +SfShow (SpecFile *sf) { + printf("<Showing Info> - specfile: %s\n",sf->sfname); + printf(" - no_scans: %ld\n",sf->no_scans); + printf(" - current: %ld\n",((SpecScan*)sf->current->contents)->scan_no); + printf(" Cursor:\n"); + printf(" - no_scans: %ld\n",sf->cursor.scanno); + printf(" - bytecnt: %ld\n",sf->cursor.bytecnt); +} + +DllExport void +SfShowScan (SpecFile *sf, long index) { + int error; + SpecScan *scan; + + printf("<Showing Info> - specfile: %s / idx %ld\n",sf->sfname,index); + + if (sfSetCurrent(sf,index,&error) == -1) { + printf("Cannot get scan index %ld\n",index); + } + + scan = (SpecScan *) sf->current->contents; + + printf(" - index: %ld\n",scan->index); + printf(" - scan_no: %ld\n",scan->scan_no); + printf(" - offset: %ld\n",scan->offset); + printf(" - data_offset: %ld\n",scan->data_offset); +} diff --git a/src/silx/io/specfile/src/sfwrite.c b/src/silx/io/specfile/src/sfwrite.c new file mode 100644 index 0000000..c77f400 --- /dev/null +++ b/src/silx/io/specfile/src/sfwrite.c @@ -0,0 +1,592 @@ +# /*########################################################################## +# Copyright (C) 1995-2017 European Synchrotron Radiation Facility +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# +# ############################################################################*/ +/************************************************************************ + * + * File: sfwrite.c + * + * Project: SpecFile library + * + * Description: Functions for scan output + * + * Author: V.Rey + * + * Date: $Date: 2003/09/12 13:20:35 $ + * + ************************************************************************/ +/* + * Log: $Log: sfwrite.c,v $ + * Log: Revision 1.1 2003/09/12 13:20:35 rey + * Log: Initial revision + * Log: + * Log: Revision 3.0 2000/12/20 14:17:19 rey + * Log: Python version available + * Log: + * Revision 2.1 2000/07/31 19:05:14 19:05:14 rey (Vicente Rey-Bakaikoa) + * SfUpdate and bug corrected in ReadIndex + * + * Revision 2.0 2000/04/13 13:28:54 13:28:54 rey (Vicente Rey-Bakaikoa) + * New version of the library. Complete rewrite + * Adds support for MCA + */ +#include <SpecFile.h> +#include <SpecFileP.h> +#ifndef WIN32 +#include <unistd.h> +#endif +/* + * Declarations + */ +DllExport SpecFileOut *SfoInit ( SpecFile *sf, int *error ); +DllExport void SfoClose ( SpecFileOut *sfo ); +DllExport long SfoSelectAll ( SpecFileOut *sfo, int *error ); +DllExport long SfoSelectOne ( SpecFileOut *sfo, long index, + int *error ); +DllExport long SfoSelect ( SpecFileOut *sfo, long *list, + int *error ); +DllExport long SfoSelectRange ( SpecFileOut *sfo, long begin, + long end, int *error ); +DllExport long SfoRemoveOne ( SpecFileOut *sfo, long index, + int *error ); +DllExport long SfoRemove ( SpecFileOut *sfo, long *list, + int *error ); +DllExport long SfoRemoveRange ( SpecFileOut *sfo, long begin, + long end, int *error ); +DllExport long SfoRemoveAll ( SpecFileOut *sfo, int *error ); +DllExport long SfoWrite ( SpecFileOut *sfo, char *name, + int *error ); +DllExport long SfoGetList ( SpecFileOut *sfo, long **list, + int *error ); + +/* + * Internal functions + */ +static int sfoWriteOne(SpecFileOut *sfo,int output, long index,int *error); + + +/********************************************************************* + * Function: SpecFileOut *SfoInit( sf, error ) + * + * Description: Initializes a SpecFileOut structure: + * - pointer to SpecFile + * - list of scans to be copied + * - size of this list + * - last written file header + * Parameters: + * Input : (1) SpecFile pointer + * + * Output: + * (2) error number + * Returns: + * Pointer to the initialized SpecFileOut structure. + * NULL in case of an error. + * + * Possible errors: + * SF_ERR_MEMOREY_ALLOC + * + * Remark: This function MUST be the FIRST called before + * any other WRITE function is called ! + * + *********************************************************************/ +DllExport SpecFileOut * +SfoInit( SpecFile *sf, int *error ) +{ + SpecFileOut *sfo; + + /* + * Alloc memory + */ + sfo = (SpecFileOut *) malloc ( sizeof(SpecFileOut) ); + + if ( sfo == (SpecFileOut *)NULL ) { + *error = SF_ERR_MEMORY_ALLOC; + return( (SpecFileOut *)NULL ); + } + + /* + * Initialize + */ + sfo->sf = sf; + sfo->list = (long *)NULL; + sfo->list_size = 0; + sfo->file_header = -1; + + return( sfo ); +} + + +/********************************************************************* + * Function: long SfoGetList( sfo, list, error ) + * + * Description: Makes a copy of the SpecFileOut list. + * + * Parameters: + * Input : (1) SpecFileOut pointer + * + * Output: (2) Copy of the output list of spec scan indices. + * (3) error code + * Returns: + * Number of scan indices in the output list , + * ( 0 ) => list empty( (long *)NULL ) ), no errors + * ( -1 ) in case of an error. + * + * Possible errors: + * SF_ERR_MEMOREY_ALLOC + * + * Remark: The memory allocated should be freed by the application + * + *********************************************************************/ +DllExport long +SfoGetList( SpecFileOut *sfo, long **list, int *error ) +{ + long i; + + *list = (long *)NULL; + + if ( sfo->list_size > 0 ) { + *list = (long *)malloc( sfo->list_size * sizeof(long) ); + if ( *list == (long *)NULL ) { + *error = SF_ERR_MEMORY_ALLOC; + return( -1 ); + } + for ( i=0 ; i < sfo->list_size ; i++ ) { + (*list)[i] = sfo->list[i]; + } + } else *list = (long *)NULL; + + return( sfo->list_size ); +} + + +/********************************************************************* + * Function: long SfoSelectOne( sfo, index, error ) + * + * Description: Adds one scan index to the SpecFileOut list. + * + * Parameters: + * Input : (1) SpecFileOut pointer + * (2) Scan index + * Output: + * (3) error code + * Returns: + * ( -1 ) => error + * Number of scan indices in the SpecFileOut list. + * + * Possible errors: + * SF_ERR_MEMORY_ALLOC + * + *********************************************************************/ +DllExport long +SfoSelectOne( SpecFileOut *sfo, long index, int *error ) +{ + long i; + + /* + * Check if index exists or if it's out of range. + */ + if ( index > sfo->sf->no_scans || index < 1 ) { + return( sfo->list_size ); + } + + /* + * Alloc memory for the new index and add it to the list. + */ + if ( sfo->list == (long *)NULL ) { + sfo->list = (long *)malloc( sizeof(long) ); + if ( sfo->list == (long *)NULL ) { + *error = SF_ERR_MEMORY_ALLOC; + return( -1 ); + } + sfo->list_size = 1; + } else { + /* + * Is the new index already in list ? + */ + for ( i=0 ; i<sfo->list_size ; i++ ) + if ( index == sfo->list[i] ) return( sfo->list_size ); + sfo->list = realloc( sfo->list, ++(sfo->list_size) * sizeof(long) ); + if ( sfo->list == (long *)NULL ) { + *error = SF_ERR_MEMORY_ALLOC; + sfo->list_size = 0; + return( -1 ); + } + } + sfo->list[sfo->list_size-1] = index; + printf("Adding scan %ld\n",index); + + return( sfo->list_size ); +} + + +/********************************************************************* + * Function: long SfoSelect( sfo, list, error ) + * + * Description: Adds several scan indices to the SpecFileOut list. + * + * Parameters: + * Input : (1) SpecFileOut pointer + * (2) List scan indices (!The last element + * MUST be a '0' !) + * Output: + * (3) error code + * Returns: + * ( -1 ) => error + * Number of scan indices in the SpecFileOut list. + * + * Possible errors: + * SF_ERR_MEMORY_ALLOC | => SfoSelectOne() + * + *********************************************************************/ +DllExport long +SfoSelect( SpecFileOut *sfo, long *list, int *error ) +{ + for ( ; *list != 0 ; list++ ) { + if ( SfoSelectOne( sfo, *list , error ) < 0 ) return( -1 ); + } + return( sfo->list_size ); +} + + +/********************************************************************* + * Function: long SfoSelectRange( sfo, begin, end, error ) + * + * Description: Adds scan indices between 'begin' and 'end' + * to the SpecFileOut list. + * + * Parameters: + * Input : (1) SpecFileOut pointer + * (2) First ... + * (3) Last index to be added + * Output: + * (4) error code + * Returns: + * ( -1 ) => error + * Number of scan indices in the SpecFileOut list. + * + * Possible errors: + * SF_ERR_MEMORY_ALLOC | => SfoSelectOne() + * + *********************************************************************/ +DllExport long +SfoSelectRange( SpecFileOut *sfo, long begin, long end, int *error ) +{ + long i; + + if ( begin > end ) { + i=begin; + begin = end; + end = i; + } + if ( begin < 1 || end > sfo->sf->no_scans ) { + return( sfo->list_size ); + } + for ( i=begin ; i<=end ; i++ ) { + if ( SfoSelectOne( sfo, i , error ) < 0 ) return( -1 ); + } + return( sfo->list_size ); +} + + +/********************************************************************* + * Function: long SfoSelectAll( sfo, error ) + * + * Description: Writes all scan indices in the SpecFileOut list. + * + * Parameters: + * Input : (1) SpecFileOutput pointer + * Output: (2) error number + * Returns: + * ( -1 ) => error + * Number of scan indices in the SpecFileOut list. + * + * Possible errors: + * SF_ERR_MEMORY_ALLOC + * + *********************************************************************/ +DllExport long +SfoSelectAll( SpecFileOut *sfo, int *error ) +{ + long i; + + if ( sfo->sf->no_scans > 0 ) { + for ( i=1 ; i<=sfo->sf->no_scans ; i++ ) { + if ( SfoSelectOne( sfo, i , error ) < 0 ) return( -1 ); + } + } + return( sfo->list_size ); +} + + +/********************************************************************* + * Function: long SfoRemoveOne( sfo, index, error ) + * + * Description: Removes one scan index from the SpecFileOut list. + * + * Parameters: + * Input : (1) SpecFileOut pointer + * (2) Scan index to be removed + * Output: + * (3) error code + * Returns: + * Number of scans left , + * ( 0 ) => list empty( (long *)NULL ) ), no errors + * ( -1 ) => error. + * + * Possible errors: + * SF_ERR_MEMORY_ALLOC + * + *********************************************************************/ +DllExport long +SfoRemoveOne( SpecFileOut *sfo, long index, int *error ) +{ + long i; + int found = 0; + + /* + * Look for scan index and delete. + */ + for ( i=0 ; i < (sfo->list_size - found) ; i++ ) { + if ( sfo->list[i] == index ) found = 1; + if ( found ) sfo->list[i]=sfo->list[i+1]; + } + + /* + * Free unused memory + */ + if ( found ) { + (sfo->list_size)--; + sfo->list = realloc( sfo->list, sfo->list_size * sizeof(long) ); + if ( sfo->list == (long *)NULL && sfo->list_size != 0 ) { + *error = SF_ERR_MEMORY_ALLOC; + return( -1 ); + } + } + return( sfo->list_size ); +} + + +/********************************************************************* + * Function: long SfoRemove( sfo, list, error ) + * + * Description: Removes several scans indices from the + * SpecFileOut list. + * + * Parameters: + * Input : (1) SpecFileOut pointer + * (2) List of scan indices to be removed + * ( !!! The last element MUST be a '0' !!! ) + * Output: + * (3) error code + * Returns: + * Number of scan indices left , + * ( 0 ) => list empty( (long *)NULL ) ), no errors + * ( -1 ) => error. + * + * Possible errors: + * SF_ERR_MEMORY_ALLOC | => SfoRemoveOne() + * + *********************************************************************/ +DllExport long +SfoRemove( SpecFileOut *sfo, long *list, int *error ) +{ + for ( ; *list != 0 ; list++ ) { + if ( SfoRemoveOne( sfo, *list , error ) < 0 ) return( -1 ); + } + return( sfo->list_size ); +} + + +/********************************************************************* + * Function: long SfoRemoveRange( sfo, begin, end, error ) + * + * Description: Removes scans indices from 'begin' to 'end' + * from the SpecFileOut list. + * + * Parameters: + * Input : + * (1) SpecFileOut pointer + * (2) First ... + * (3) Last index to be removed + * Output: + * (4) error code + * Returns: + * Number of scan indices left , + * ( 0 ) => list empty( (long *)NULL ) ), no errors + * ( -1 ) => error. + * + * Possible errors: + * SF_ERR_MEMORY_ALLOC | => SfoRemoveOne() + * + *********************************************************************/ +DllExport long +SfoRemoveRange( SpecFileOut *sfo, long begin, long end, int *error ) +{ + long i; + + if ( begin > end ) { + i=begin; + begin = end; + end = i; + } + if ( begin < 1 || end > sfo->sf->no_scans ) { + return( sfo->list_size ); + } + for ( i=begin ; i <= end ; i++ ) { + if ( SfoRemoveOne( sfo, i, error ) < 0 ) return( -1 ); + } + return( sfo->list_size ); +} + + +/********************************************************************* + * Function: long SfoRemoveAll( sfo, error ) + * + * Description: Removes all scans indices + * from the SpecFileOut list. + * + * Parameters: + * Input : + * (1) SpecFileOut pointer + * Output: + * (2) error code + * Returns: + * ( 0 ) => OK + * + *********************************************************************/ +DllExport long +SfoRemoveAll( SpecFileOut *sfo, int *error ) +{ + free( sfo->list ); + sfo->list = (long *)NULL; + sfo->list_size = 0; + sfo->file_header = -1; + return( 0 ); +} + + +/********************************************************************* + * Function: int SfoWrite( sfo, name, error ) + * + * Description: Writes (appends) SpecScans specified in the sfo->list + * in the file 'name'. Related file headers are copied + * too. + * Parameters: + * Input : (1) SpecFileOut pointer + * (2) Output file name + * Output: + * (3) error number + * Returns: + * Number of written scans, + * (-1 ) => Errors occured + * Possible errors: + * SF_ERR_FILE_WRITE | => cpyBlock() + * SF_ERR_FILE_READ + * SF_ERR_FILE_OPEN + * SF_ERR_FILE_CLOSE + * + *********************************************************************/ +DllExport long +SfoWrite( SpecFileOut *sfo, char *name, int *error ) +{ + int output; + long i; + + if ( sfo == (SpecFileOut *)NULL || sfo->list_size<1 ) return( 0 ); + + /* + * Open file + */ + if ( (output = open(name, O_CREAT | O_RDWR | O_APPEND, SF_UMASK )) == (int)NULL ) { + *error = SF_ERR_FILE_OPEN; + return( -1 ); + } + + for ( i=0 ; i < sfo->list_size ; i++ ) + sfoWriteOne(sfo,output,sfo->list[i],error); + + if ( close( output ) ) { + *error = SF_ERR_FILE_CLOSE; + return( -1 ); + } + + return( sfo->list_size ); +} + + +/********************************************************************* + * Function: int SfoClose( sfo ) + * + * Description: Frees all memory used by + * SpecFileOut structure. + * Parameters: + * Input : (1) SpecFileOut pointer + * + * Remark: This function should be called after all + * writing operations. + * + *********************************************************************/ +DllExport void +SfoClose( SpecFileOut *sfo ) +{ + /* + * Free memory. + */ + free( sfo->list ); + free( sfo ); +} + + +static int +sfoWriteOne(SpecFileOut *sfo,int output,long index,int *error) +{ + long file_header,size; + SpecFile *sf; + + if ( sfSetCurrent(sfo->sf,index,error) == -1 ) { + *error = SF_ERR_SCAN_NOT_FOUND; + return(-1); + } + + /* + * File header + */ + sf = sfo->sf; + + file_header = ((SpecScan *)sf->current->contents)->size; + + if (file_header != -1 && file_header != sfo->file_header ) { + printf("Writing %ld bytes\n",sf->filebuffersize); + write(output, (void *) sf->filebuffer, sf->filebuffersize); + sfo->file_header = file_header; + } + + /* + * write scan + */ + size = ((SpecScan *)sf->current->contents)->size; + + if ( write(output,(void *) sf->scanbuffer,size) == -1 ) { + *error = SF_ERR_FILE_WRITE; + return(-1); + } + return(0); +} |