From 2d4076c19b84195622040b39ef60931c7ec103d0 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de>
Date: Wed, 11 Jan 2017 10:16:17 +0100
Subject: [PATCH] Revert "Remove loaders for old formats 96 and 01."

This reverts commit bf40c65f1144753631ce10a8e05bb7603629a00a.
---
 pub/lib/coord.cpp   |  24 ++++
 pub/lib/coord.hpp   |   4 +-
 pub/lib/file_in.cpp | 313 ++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 332 insertions(+), 9 deletions(-)

diff --git a/pub/lib/coord.cpp b/pub/lib/coord.cpp
index f216cfdd..34ead200 100644
--- a/pub/lib/coord.cpp
+++ b/pub/lib/coord.cpp
@@ -127,6 +127,30 @@ string CCoord::str_ps() const // two blanks instead of one, and no unit ""
     return name + ( unit!="" ? ("  (" + unit + ")") : "");
 }
 
+//! Parse old a01 format.
+
+string CCoord::load_a01(string in)
+{
+    string::size_type t1, t2;
+    if(!in.size()) {
+        name = "";
+        unit = "";
+        return "";
+    }
+    if ((t1 = in.find('\t'))==string::npos) {
+        name = in;
+        unit = "";
+        return "";
+    }
+    name = in.substr(0,t1);
+    if ((t2 = in.find('\t', t1+1))==string::npos) {
+        unit = in.substr(t1+1);
+        return "";
+    }
+    unit = in.substr(t1+1,t2-t1);
+    return in.substr(t2+1);
+}
+
 //**************************************************************************************************
 //*  outside CCoord
 //**************************************************************************************************
diff --git a/pub/lib/coord.hpp b/pub/lib/coord.hpp
index 05ef97c3..10ec7f4b 100644
--- a/pub/lib/coord.hpp
+++ b/pub/lib/coord.hpp
@@ -28,6 +28,8 @@ class CCoord {
     string str_std() const;
     string str_compact( int maxlen=0 ) const;
     string str_ps() const;
+    string to_a01() const;
+    string load_a01(string);
 
     //! Has this instance nonvoid contents?
     bool defined() { return name!=""; }
@@ -54,4 +56,4 @@ class CParam {
     //! Creates instance with fully given, partly unparsed contents.
     CParam( string _name, string _unit="", double _val=0, double _dval=0 ) :
         Co( CCoord(_name, _unit) ), val(_val), dval(_dval) {}
-};
+};
\ No newline at end of file
diff --git a/pub/lib/file_in.cpp b/pub/lib/file_in.cpp
index c57ffa10..369a2e10 100644
--- a/pub/lib/file_in.cpp
+++ b/pub/lib/file_in.cpp
@@ -10,6 +10,7 @@
 #include "defs.hpp"
 
 #include <fstream>
+#include <string.h>
 
 #include <yaml-cpp/yaml.h>
 
@@ -26,6 +27,10 @@
 
 namespace NFileIn {
     void Load_yda( std::ifstream& F_in, string fnam );
+    void Load_08( std::ifstream& F_in, string flong );
+    void Load_01( FILE *F_in, string flong );
+    void LoadSpec_01( FILE *F_in, PSpec& sout, int nz );
+    void Load_96( FILE *F_in, string flong );
 }
 
 
@@ -34,19 +39,30 @@ namespace NFileIn {
 void NFileIn::load(void)
 {
     string pattern = sask( "Load file(s)" );
-    vector<string> fNames = triv::glob_file_list( pattern, "yda y08" );
+    vector<string> fNames = triv::glob_file_list( pattern, "yda y08 a01 i96" );
     for( string fnam: fNames ) {
         try{
             string fdir, fshort, fext;
             triv::fname_divide( fnam, &fdir, &fshort, &fext);
-            if ( !(fext=="y08" || fext=="yda") )
+            if ( fext=="y08" || fext=="yda" ) {
+                std::ifstream FS (fnam.c_str(), std::ios_base::in);
+                if( FS.fail() )
+                    throw string("cannot open file");
+                cout << ".. loading file " << fnam << "\n";
+                Load_yda( FS, fshort );
+                FS.close();
+            } else if ( fext=="a01" || fext=="i96" ) {
+                FILE *F_in;
+                if( !(F_in = fopen(fnam.c_str(), "r")) )
+                    throw "cannot open file " + fnam;
+                if ( fext=="a01" ) {
+                    Load_01( F_in, fnam.c_str() );
+                } else if ( fext=="i96" ) {
+                    Load_96( F_in, fnam.c_str() );
+                }
+                fclose( F_in );
+            } else
                 throw "unknown extension " + fext;
-            std::ifstream FS (fnam.c_str(), std::ios_base::in);
-            if( FS.fail() )
-                throw string("cannot open file");
-            cout << ".. loading file " << fnam << "\n";
-            Load_yda( FS, fshort );
-            FS.close();
         }
         catch(string& ex) {
             throw "Cannot load " + fnam + ": " + ex;
@@ -337,3 +353,284 @@ void NFileIn::Load_yda(std::ifstream& FS, string fnam)
     fout->as_on_disk = true;
     SMem::instance()->mem_store( move(fout) );
 }
+
+
+//! Load a .a01 formatted file.
+
+void NFileIn::Load_01( FILE *F_in, string flong )
+{
+    string lin, key, val, fdir, fshort, fext;
+    int iz, nj=0, j;
+    CCoord co;
+    POld fout( new COld );
+
+    triv::fname_divide( flong, &fdir, &fshort, &fext);
+
+    if     ( triv::freadln(F_in, &lin)<=0 )
+        throw  "file empty or starting with empty line";
+    if     ( lin!=string("ASCII-01 JWu") )
+        throw ".a01 file starts with illegal header [" + lin + "]";
+
+    if ( triv::freadln(F_in, &lin)<=0 || lin.length()<5 ||
+         lin.substr(0,4)!=string("typ ") )
+        throw "no valid typ line";
+    if        ( lin.substr(4)=="D" ) {
+        // ok
+    } else if ( lin.substr(4)=="C" ) {
+        throw "reading curve files not implemented";
+    } else {
+        throw "invalid type [" + lin.substr(4) + "]";
+    }
+
+    while (1) { // loop over input lines
+        if ( !triv::freadln(F_in, &lin) )
+            throw "unexpected end-of-file";
+
+        // regular exit when "eof" is reached:
+        if ( lin=="eof" ) {
+            fout->as_on_disk = true;
+            SMem::instance()->mem_store( move(fout) );
+            return;
+        }
+
+        if ( lin.size() < 4 )
+            throw "incomplete line";
+
+        key = lin.substr(0,4);
+        val = lin.substr(4);
+
+        if        (key=="fil ") {
+            if (val!=fshort) {
+                cout << "warning: file '" << fshort <<
+                    "' renamed from '" << val << "'\n";
+            }
+            fout->name = fshort;
+        } else if (key=="doc ") {
+            fout->lDoc.push_back(val);
+        } else if (key=="x   ") {
+            fout->xco.load_a01(val);
+        } else if (key=="y   ") {
+            fout->yco.load_a01(val);
+        } else if (lin[0]=='z') {
+            if ( sscanf(lin.substr(1,3).c_str(), "%i", &iz)!=1 )
+                throw "z coordinates must be numbered";
+            if ( iz!=fout->ZCo.size() )
+                throw "z coordinates must be sorted";
+            co.load_a01(val);
+            fout->ZCo.push_back(co);
+        } else if (lin.substr(0,4)=="rpa ") {
+            string in = lin.substr(4);
+            int ji = in.find_first_not_of(" \t");
+            double dval;
+            if( ji>=20 || !triv::any2dbl( in.substr(ji,20), &dval ) )
+                throw "invalid rpa line\n";
+            fout->RPar.push_back( CParam( CCoord(), dval ) );
+            throw "a01 file contains rpa section. "
+                "Check the source code preceeding this error message. "
+                "It is possibly broken. If not, remove this exception.";
+        } else if (key=="#j  ") {
+            if ( sscanf(val.c_str(), "%i", &nj)!=1 )
+               throw "after key #j no no. of spectra";
+        } else if (key=="scn ") {
+            if ( sscanf(val.c_str(), "%i", &j)!=1 ) {
+                cout << "warning: number of spectra not given\n";
+            } else if ( j!=fout->nJ() ) {
+                cout << "warning: spec " << fout->nJ() <<
+                    " has label " << j << "\n";
+            }
+            PSpec sout( new CSpec );
+            LoadSpec_01( F_in, sout, fout->nZ() );
+            fout->V.push_back( move(sout) );
+        } else {
+            throw "Unexpected key [" + key + "]";
+        }
+    }
+}
+
+
+//! Load a spectrum from a .a01 formatted files.
+
+void NFileIn::LoadSpec_01( FILE *F_in, PSpec& sout, int nz )
+{
+    int err;
+    int i, m, n;
+    char lab[4];
+    double v, w;
+
+    // get z values:
+    if ((err=fscanf(F_in, "%4c%i\n", lab, &m))!=2)
+        throw "expecting Z head line, found " + S(err) + " entries";
+    if (strncmp(lab, "Z   ", 4))
+        throw "found [" + string(lab) + "] in Z head line";
+    if (m!=nz)
+        throw "found " + S(m) + " Z entries, expecting " + S(nz);
+    for ( i=0; i<nz; ++i ) {
+        if ((err=fscanf(F_in, "%lg\n", &v))!=1)
+            throw "expecting z value, found " + S(err) + " entries";
+        sout->z.push_back( PObjDbl( new CObjDbl( v ) ) );
+    }
+
+    // get xy values:
+    if ( (err=fscanf(F_in, "%4c%i\n", lab, &n))!=2 )
+        throw "expecting XY head line, found " + S(err) + " entries";
+    if (strncmp(lab, "XY  ", 4) )
+        throw "found [" + string(lab) + "] in XY head line";
+
+    for (i=0; i<n; i++) {
+        if ((err=fscanf(F_in, "%lg %lg\n", &v, &w))!=2) {
+            throw "expecting xy pair, found S(err) entries";
+        }
+        sout->push_xy(v, w);
+    }
+}
+
+
+//! Load a .i96 formatted file.
+
+void NFileIn::Load_96( FILE *F_in, string flong )
+{
+    string lin, key, val, fdir, fshort, fext;
+    double r0, r1, r2;
+    int n, nspec, ival;
+    POld fout( new COld );
+    CCoord co;
+    PSpec sout;
+
+    triv::fname_divide( flong, &fdir, &fshort, &fext);
+    fout->name = fshort;
+
+    if     ( !triv::freadln(F_in, &lin) )
+        throw "file empty or starting with empty line";
+    if     ( lin!=string("ASCII-96") )
+        throw ".i96 file starts with illegal header [" + lin + "]";
+
+    if ( !triv::freadln(F_in, &lin) || lin.length()<9 ||
+         lin.substr(0,9)!=string("(a24,a56)") )
+        throw "no valid intro to block 2";
+
+    if ( !triv::freadln(F_in, &lin) || lin.length()<24 ||
+         lin.substr(0,3)!=string("fil") )
+        throw "tag 'fil' not found in block 2";
+    if ( triv::strip(lin.substr(24))!=fshort ) {
+                cout << "warning: i96 file '" << fshort <<
+                    "' renamed from '" << lin.substr(24) << "'\n";
+    }
+
+    if ( !triv::freadln(F_in, &lin) || lin.length()<24 ||
+         lin.substr(0,3)!=string("tit") )
+        throw "tag 'tit' not found in block 2";
+    fout->lDoc.push_back( triv::strip(lin.substr(24)) );
+
+    while( !triv::freadln(F_in, &lin) && lin.length()>=24 &&
+         lin.substr(0,3)==string("doc") )
+        fout->lDoc.push_back( triv::strip(lin.substr(24)) );
+
+    if( lin.substr(0,3)!=string("dir") )
+        throw "tag 'dir' not found in block 2";
+
+    while ( triv::freadln(F_in, &lin) &&
+            !( lin.length()>=6 &&
+               lin.substr(0,6)==string("&eob 2") ) )
+        ;
+
+    if ( !triv::freadln(F_in, &lin) )
+        throw "missed &eob 3";
+
+    if( lin.length()<9 || lin.substr(0,9)!=string("(a24,i16)") )
+        throw "no valid intro to block 3";
+
+    while ( !triv::freadln(F_in, &lin) &&
+            !( lin.length()>=6 &&
+               lin.substr(0,6)==string("&eob 3") ) )
+        ;
+
+    if ( !triv::freadln(F_in, &lin) )
+        throw "missed &eob 3";
+
+    if ( lin.length()<16 || lin.substr(0,16)!=string("(a24,a24,g20.10)") )
+        throw "no valid intro to block 4";
+
+    while ( !triv::freadln(F_in, &lin) && lin.length()>=48 &&
+            lin.substr(0,4)!=string("&eob") ){
+        if( sscanf( lin.substr(48).c_str(), "%lg", &r0 )!=1 )
+            throw "no real value in rpar line";
+        fout->RPar.push_back(
+            CParam( lin.substr(0,24), lin.substr(24,24), r0 ) );
+    }
+
+    if( lin.substr(0,6)!=string("&eob 4") )
+        throw "no valid eob 4";
+
+    if ( !triv::freadln(F_in, &lin) || lin.length()<9 ||
+         lin.substr(0,12)!=string("(a4,a24,a24)") )
+        throw "no valid intro to block 5";
+
+    if ( !triv::freadln(F_in, &lin) || lin.length()<28 ||
+         lin.substr(0,1)!=string("x") )
+        throw "no x coordinate";
+    fout->xco = CCoord( triv::strip(lin.substr(4,24)),
+                        triv::strip(lin.substr(28,24)) );
+
+    if ( !triv::freadln(F_in, &lin) || lin.length()<28 ||
+         lin.substr(0,1)!=string("y") )
+        throw "no y coordinate";
+    fout->yco = CCoord( triv::strip(lin.substr(4,24)),
+                        triv::strip(lin.substr(28,24)) );
+
+    if ( !triv::freadln(F_in, &lin) || lin.length()<28 ||
+         lin.substr(0,1)!=string("z") )
+        throw "no z coordinate";
+    fout->ZCo.push_back( CCoord( triv::strip(lin.substr(4,24)),
+                                 triv::strip(lin.substr(28,24)) ) );
+
+    if ( !triv::freadln(F_in, &lin) || lin.length()<6 ||
+         lin.substr(0,6)!=string("&eob 5") )
+        throw "no valid eob 5";
+
+    if ( !triv::freadln(F_in, &lin) || lin.length()<5 ||
+         lin.substr(0,5)!=string("(a80)") )
+        throw "no valid intro to block 6";
+
+    while ( triv::freadln(F_in, &lin)>0 &&
+            !( lin.length()>=6 &&
+               lin.substr(0,6)==string("&eob 6") ) )
+        fout->lDoc.push_back( lin );
+
+    if ( !triv::freadln(F_in, &lin) )
+        throw "missed &eob 6";
+    for( int i=1; i<3; ++i )
+        if ( !triv::freadln(F_in, &lin) )
+            throw "no valid intro to block 7";
+
+    if ( !triv::freadln(F_in, &lin) ||
+         sscanf( lin.c_str(), "%i %i", &nspec, &ival )!=2 )
+            throw "no nspec or 2nd arg in intro to block 7";
+
+    for( int j=0; j<nspec; ++j ){
+        sout = PSpec( new CSpec );
+        if ( !triv::freadln(F_in, &lin) || lin.length()<10 ||
+             lin.substr(0,9)!=string("&spectrum") ||
+             sscanf( lin.substr(10).c_str(), "%i", &ival )!=1 ||
+             ival!=j+1 )
+            throw "no valid intro to spectrum";
+
+        if ( !triv::freadln(F_in, &lin) ||
+             sscanf( lin.c_str(), "%i %lg", &n, &r0 )!=2 )
+            throw "no valid header in spectrum";
+        sout->z.push_back( PObjDbl( new CObjDbl( r0 ) ) );
+
+        for( int i=0; i<n; ++i ){
+            if ( !F_in || !triv::freadln(F_in, &lin) )
+                throw "i96: failed to read data line " +
+                    S(i) + " of " + S(n);
+            if ( sscanf( lin.c_str(), "%lg %lg %lg", &r0, &r1, &r2 )!=3 )
+                throw "i96: bad data line: '" + lin + "'";
+            sout->push_xy(r0, r1);
+        }
+
+        fout->V.push_back( move(sout) );
+    }
+
+    fout->as_on_disk = true;
+    SMem::instance()->mem_store( move(fout) );
+}
-- 
GitLab