summaryrefslogtreecommitdiff
path: root/src/silx/io/specfile/src
diff options
context:
space:
mode:
Diffstat (limited to 'src/silx/io/specfile/src')
-rw-r--r--src/silx/io/specfile/src/locale_management.c79
-rw-r--r--src/silx/io/specfile/src/sfdata.c757
-rw-r--r--src/silx/io/specfile/src/sfheader.c792
-rw-r--r--src/silx/io/specfile/src/sfindex.c556
-rw-r--r--src/silx/io/specfile/src/sfinit.c830
-rw-r--r--src/silx/io/specfile/src/sflabel.c654
-rw-r--r--src/silx/io/specfile/src/sflists.c189
-rw-r--r--src/silx/io/specfile/src/sfmca.c341
-rw-r--r--src/silx/io/specfile/src/sftools.c554
-rw-r--r--src/silx/io/specfile/src/sfwrite.c592
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);
+}