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