From 4db7ae9abbc3c639dd62b9d9d471a59e605a8f89 Mon Sep 17 00:00:00 2001
From: ralfulrich <ralf.ulrich@kit.edu>
Date: Sat, 18 Jul 2020 10:18:56 +0200
Subject: [PATCH] properly copy fortran string into c++ string

---
 readLib/corsika_data/Interface.h  |  2 +-
 readLib/source/Interface.boost.cc | 27 +++++++++++---
 readLib/source/Interface.dummy.cc |  4 ++-
 readLib/source/testData.cc        | 60 ++++++++++++++++++++++++++++---
 4 files changed, 83 insertions(+), 10 deletions(-)

diff --git a/readLib/corsika_data/Interface.h b/readLib/corsika_data/Interface.h
index 656e4ca..3574010 100644
--- a/readLib/corsika_data/Interface.h
+++ b/readLib/corsika_data/Interface.h
@@ -24,7 +24,7 @@ namespace corsika_data {
 
   // the fortran interface functions
   extern "C" {
-  void cordataopenfile_(const char*);
+  void cordataopenfile_(const char*, const int stringlength);
   void cordatafillarray_(double*, const int&);
   void cordataclosefile_();
   double cordatanextnumber_();
diff --git a/readLib/source/Interface.boost.cc b/readLib/source/Interface.boost.cc
index d772695..19d6da4 100644
--- a/readLib/source/Interface.boost.cc
+++ b/readLib/source/Interface.boost.cc
@@ -29,27 +29,39 @@ namespace corsika_data {
         std::cout << "DataFile is still open! Closing it now..." << std::endl;
         file_in_.close();
       }
+      in_.reset();
       std::string s(name);
       auto i1 = s.find_first_not_of(" \t\r\n"); // trimm right
       auto i2 = s.find_first_of(" \t\r\n", i1); // trimm left
       std::string trimmed(s.substr(i1, i2 - i1));
       file_in_.open(trimmed, ios_base::in | ios_base::binary);
-      in_.reset();
+      if (!file_in_ || !file_in_.good()) {
+        std::cerr << std::string("Cannot open file: \'") + trimmed << "\'" << std::endl;
+        throw std::runtime_error(std::string("Cannot open file: ") + trimmed);
+      }
       if (trimmed.rfind(".bz2") == trimmed.length() - 4)
         in_.push(boost::iostreams::bzip2_decompressor());
       in_.push(file_in_);
     }
     void Close() { file_in_.close(); }
     void FillArray(double* data, const int& length) {
-      for (int i = 0; i < length; i++) in_ >> data[i];
+      for (int i = 0; i < length; i++) {
+        in_ >> data[i];
+        if (!in_.good()) {
+          throw std::runtime_error(std::string("Cannot FillArray i=") +
+                                   std::to_string(i));
+        }
+      }
     }
     double ReadNextNumber() {
       double data;
       in_ >> data;
+      if (!in_.good()) { throw std::runtime_error(std::string("Cannot ReadNextNumber")); }
       return data;
     }
     int ReadNextText(std::string& data) {
       std::getline(in_, data, ' ');
+      if (!in_.good()) { throw std::runtime_error(std::string("Cannot ReadNextText")); }
       return 0;
     }
   };
@@ -57,7 +69,6 @@ namespace corsika_data {
   DataFile global_DataFile;
 
   void CorDataOpenFile(const std::string& name) { global_DataFile.Open(name.c_str()); }
-  // void CorDataOpenFile(const char* name) { global_DataFile.Open(name); }
   void CorDataFillArray(double* data, const int& length) {
     global_DataFile.FillArray(data, length);
   }
@@ -72,7 +83,15 @@ namespace corsika_data {
   bool CorDataCanDeCompress() { return true; }
 
   extern "C" {
-  void cordataopenfile_(const char* name) { CorDataOpenFile(name); }
+  void cordataopenfile_(const char* name, const int stringlength) {
+    // make a 'real' string out of fortran one (if \0 is missing)
+    char *buffer = new char[stringlength + 1];
+    for (int i = 0; i < stringlength; ++i) buffer[i] = name[i];
+    // if not already terminated by 0, add it
+    if (buffer[stringlength - 1] != '\0') buffer[stringlength] = '\0';
+    CorDataOpenFile(buffer);
+    delete [] buffer;
+  }
   void cordatafillarray_(double* data, const int& length) {
     global_DataFile.FillArray(data, length);
   }
diff --git a/readLib/source/Interface.dummy.cc b/readLib/source/Interface.dummy.cc
index c360493..a84753f 100644
--- a/readLib/source/Interface.dummy.cc
+++ b/readLib/source/Interface.dummy.cc
@@ -41,7 +41,9 @@ namespace corsika_data {
 
   // the fortran interface functions
   extern "C" {
-  void cordataopenfile_(const char* name) { CorDataOpenFile(name); }
+  void cordataopenfile_(const char* name, const int stringlength) {
+    CorDataOpenFile(name);
+  }
   void cordatafillarray_(double* data, const int& length) {
     CorDataFillArray(data, length);
   }
diff --git a/readLib/source/testData.cc b/readLib/source/testData.cc
index cd3b3a5..1d0831b 100644
--- a/readLib/source/testData.cc
+++ b/readLib/source/testData.cc
@@ -37,7 +37,7 @@ TEST_CASE("Data", "[data]") {
   SECTION(std::string("c++,") + file) {
     bool b = CorDataCanDeCompress();
     CHECK(b == true);
-    cout << "Reading: " << file << endl;
+    cout << "Open/Reading: " << file << endl;
     CorDataOpenFile(file);
     std::string str;
     CorDataNextText(str);
@@ -61,8 +61,60 @@ TEST_CASE("Data", "[data]") {
     int i = 0;
     cordatacandecompress_(i);
     CHECK(i == 1);
-    cout << "Reading: " << file << endl;
-    cordataopenfile_(file.c_str());
+    cout << "Open/Reading: " << file << endl;
+    cordataopenfile_(file.c_str(), file.length());
+    char str[10];
+    cordatanexttext_(str, 10);
+    CHECK(std::string(str) == "sibyll20");
+    CHECK(cordatanextnumber_() == 0.10000E-02);
+    CHECK(cordatanextnumber_() == 91);
+    CHECK(cordatanextnumber_() == 261);
+    CHECK(cordatanextnumber_() == 5);
+    CHECK(cordatanextnumber_() == 11);
+    CHECK(cordatanextnumber_() == 20);
+
+    double aData[3 * 9];
+    const int length = 3 * 9;
+    cordatafillarray_(aData, length);
+
+    for (int i = 0; i < length; ++i) { CHECK(aData[i] == testData[i]); }
+    cordataclosefile_();
+  }
+
+  // now read file two times in a row
+  SECTION(std::string("twice, c++,") + file) {
+    bool b = CorDataCanDeCompress();
+    CHECK(b == true);
+    cout << "Open/Close/Open/Reading: " << file << endl;
+    CorDataOpenFile(file);
+    CorDataCloseFile();
+    CorDataOpenFile(file);
+    std::string str;
+    CorDataNextText(str);
+    CHECK(str == "sibyll20");
+    CHECK(CorDataNextNumber() == 0.10000E-02);
+    CHECK(CorDataNextNumber() == 91);
+    CHECK(CorDataNextNumber() == 261);
+    CHECK(CorDataNextNumber() == 5);
+    CHECK(CorDataNextNumber() == 11);
+    CHECK(CorDataNextNumber() == 20);
+
+    double aData[3 * 9];
+    const int length = 3 * 9;
+    CorDataFillArray(aData, length);
+
+    for (int i = 0; i < length; ++i) { CHECK(aData[i] == testData[i]); }
+    CorDataCloseFile();
+  }
+
+  SECTION(std::string("twice, fortran, ") + file) {
+    int i = 0;
+    cordatacandecompress_(i);
+    CHECK(i == 1);
+    cout << "Open/Close/Open/Reading: " << file << endl;
+    cordataopenfile_(file.c_str(), file.length());
+    cordataclosefile_();
+    cordataopenfile_(file.c_str(), file.length());
     char str[10];
     cordatanexttext_(str, 10);
     CHECK(std::string(str) == "sibyll20");
@@ -97,7 +149,7 @@ TEST_CASE("Data", "[data]") {
   }
 
   SECTION("fortran") {
-    CHECK_THROWS(cordataopenfile_(""));
+    CHECK_THROWS(cordataopenfile_(""), 0);
     double a[1];
     const int length = 1;
     CHECK_THROWS(cordatafillarray_(a, length));
-- 
GitLab