| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // This file is part of INSTINCT, the INS Toolkit for Integrated | ||
| 2 | // Navigation Concepts and Training by the Institute of Navigation of | ||
| 3 | // the University of Stuttgart, Germany. | ||
| 4 | // | ||
| 5 | // This Source Code Form is subject to the terms of the Mozilla Public | ||
| 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this | ||
| 7 | // file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||
| 8 | |||
| 9 | #include "FileReader.hpp" | ||
| 10 | |||
| 11 | #include "util/Logger.hpp" | ||
| 12 | |||
| 13 | #include "internal/ConfigManager.hpp" | ||
| 14 | #include "internal/FlowManager.hpp" | ||
| 15 | |||
| 16 | #include <sstream> | ||
| 17 | #include "util/StringUtil.hpp" | ||
| 18 | |||
| 19 | #include <imgui.h> | ||
| 20 | #include "internal/gui/widgets/FileDialog.hpp" | ||
| 21 | #include "internal/gui/widgets/HelpMarker.hpp" | ||
| 22 | |||
| 23 | ✗ | NAV::FileReader::GuiResult NAV::FileReader::guiConfig(const char* vFilters, const std::vector<std::string>& extensions, size_t id, const std::string& nameId) | |
| 24 | { | ||
| 25 | ✗ | GuiResult result = PATH_UNCHANGED; | |
| 26 | |||
| 27 | ✗ | if (gui::widgets::FileDialogLoad(_path, "Select File", vFilters, extensions, flow::GetInputPath(), id, nameId)) | |
| 28 | { | ||
| 29 | ✗ | if (!std::filesystem::exists(getFilepath())) | |
| 30 | { | ||
| 31 | ✗ | result = PATH_CHANGED_INVALID; | |
| 32 | } | ||
| 33 | else | ||
| 34 | { | ||
| 35 | ✗ | result = PATH_CHANGED; | |
| 36 | } | ||
| 37 | } | ||
| 38 | ✗ | ImGui::SameLine(); | |
| 39 | ✗ | gui::widgets::HelpMarker(fmt::format("If a relative path is given, files will be searched inside {}.", flow::GetInputPath()).c_str()); | |
| 40 | |||
| 41 | ✗ | return result; | |
| 42 | } | ||
| 43 | |||
| 44 | 328 | std::filesystem::path NAV::FileReader::getFilepath() | |
| 45 | { | ||
| 46 | 328 | std::filesystem::path filepath{ _path }; | |
| 47 |
1/2✓ Branch 1 taken 329 times.
✗ Branch 2 not taken.
|
328 | if (filepath.is_relative()) |
| 48 | { | ||
| 49 |
1/2✓ Branch 1 taken 328 times.
✗ Branch 2 not taken.
|
329 | filepath = flow::GetInputPath(); |
| 50 |
1/2✓ Branch 1 taken 329 times.
✗ Branch 2 not taken.
|
325 | filepath /= _path; |
| 51 | } | ||
| 52 | 329 | return filepath; | |
| 53 | ✗ | } | |
| 54 | |||
| 55 | ✗ | [[nodiscard]] json NAV::FileReader::save() const | |
| 56 | { | ||
| 57 | LOG_TRACE("called"); | ||
| 58 | |||
| 59 | ✗ | json j; | |
| 60 | |||
| 61 | ✗ | j["path"] = _path; | |
| 62 | |||
| 63 | ✗ | return j; | |
| 64 | ✗ | } | |
| 65 | |||
| 66 | 166 | void NAV::FileReader::restore(json const& j) | |
| 67 | { | ||
| 68 | LOG_TRACE("called"); | ||
| 69 | |||
| 70 |
1/2✓ Branch 1 taken 166 times.
✗ Branch 2 not taken.
|
166 | if (j.contains("path")) |
| 71 | { | ||
| 72 | 166 | j.at("path").get_to(_path); | |
| 73 | } | ||
| 74 | 166 | } | |
| 75 | |||
| 76 | 166 | bool NAV::FileReader::initialize() | |
| 77 | { | ||
| 78 |
1/2✓ Branch 1 taken 166 times.
✗ Branch 2 not taken.
|
166 | deinitialize(); |
| 79 | |||
| 80 | LOG_TRACE("called"); | ||
| 81 | |||
| 82 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 166 times.
|
166 | if (_path.empty()) |
| 83 | { | ||
| 84 | ✗ | return false; | |
| 85 | } | ||
| 86 | |||
| 87 |
1/2✓ Branch 1 taken 165 times.
✗ Branch 2 not taken.
|
166 | std::filesystem::path filepath = getFilepath(); |
| 88 | |||
| 89 |
2/4✓ Branch 1 taken 164 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 164 times.
|
165 | if (!std::filesystem::exists(filepath)) |
| 90 | { | ||
| 91 | ✗ | LOG_ERROR("File does not exist {}", filepath); | |
| 92 | ✗ | return false; | |
| 93 | } | ||
| 94 |
2/4✓ Branch 1 taken 165 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 165 times.
|
164 | if (std::filesystem::is_directory(filepath)) |
| 95 | { | ||
| 96 | ✗ | LOG_ERROR("Path is a directory {}", filepath); | |
| 97 | ✗ | return false; | |
| 98 | } | ||
| 99 | |||
| 100 |
1/2✓ Branch 1 taken 163 times.
✗ Branch 2 not taken.
|
165 | _fileType = determineFileType(); |
| 101 | |||
| 102 |
4/4✓ Branch 0 taken 8 times.
✓ Branch 1 taken 155 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 1 times.
|
163 | if (_fileType == FileType::ASCII || _fileType == FileType::BINARY) |
| 103 | { | ||
| 104 | // Does not enable binary read/write, but disables OS dependant treatment of \n, \r | ||
| 105 |
2/4✓ Branch 2 taken 165 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 162 times.
✗ Branch 6 not taken.
|
162 | _filestream = std::ifstream(filepath, std::ios_base::in | std::ios_base::binary); |
| 106 | } | ||
| 107 | else | ||
| 108 | { | ||
| 109 | 1 | return false; | |
| 110 | } | ||
| 111 | |||
| 112 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 165 times.
|
165 | if (!_filestream.good()) |
| 113 | { | ||
| 114 | ✗ | LOG_ERROR("Could not open file {}", filepath); | |
| 115 | ✗ | return false; | |
| 116 | } | ||
| 117 | 165 | _lineCnt = 0; | |
| 118 | |||
| 119 |
1/2✓ Branch 1 taken 165 times.
✗ Branch 2 not taken.
|
165 | readHeader(); |
| 120 | |||
| 121 | 165 | _lineCntDataStart = _lineCnt; | |
| 122 |
1/2✓ Branch 1 taken 164 times.
✗ Branch 2 not taken.
|
165 | _dataStart = _filestream.tellg(); |
| 123 | |||
| 124 |
2/2✓ Branch 0 taken 157 times.
✓ Branch 1 taken 7 times.
|
164 | if (_fileType == FileType::ASCII) |
| 125 | { | ||
| 126 |
2/4✓ Branch 1 taken 158 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 158 times.
✗ Branch 7 not taken.
|
315 | LOG_DEBUG("ASCII-File successfully initialized"); |
| 127 | } | ||
| 128 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | else if (_fileType == FileType::BINARY) |
| 129 | { | ||
| 130 |
2/4✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 7 times.
✗ Branch 7 not taken.
|
14 | LOG_DEBUG("Binary-File successfully initialized"); |
| 131 | } | ||
| 132 | |||
| 133 | 165 | return true; | |
| 134 | 166 | } | |
| 135 | |||
| 136 | 331 | void NAV::FileReader::deinitialize() | |
| 137 | { | ||
| 138 | LOG_TRACE("called"); | ||
| 139 | |||
| 140 | 331 | _headerColumns.clear(); | |
| 141 | |||
| 142 |
2/2✓ Branch 1 taken 165 times.
✓ Branch 2 taken 166 times.
|
331 | if (_filestream.is_open()) |
| 143 | { | ||
| 144 | 165 | _filestream.close(); | |
| 145 | } | ||
| 146 | |||
| 147 | 331 | _filestream.clear(); | |
| 148 | 331 | } | |
| 149 | |||
| 150 | 1 | NAV::FileReader::FileType NAV::FileReader::determineFileType() | |
| 151 | { | ||
| 152 | LOG_TRACE("called"); | ||
| 153 | |||
| 154 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | auto filepath = getFilepath(); |
| 155 | |||
| 156 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | auto filestreamHeader = std::ifstream(filepath); |
| 157 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | if (_filestream.good()) |
| 158 | { | ||
| 159 | 1 | std::string line; | |
| 160 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | std::getline(filestreamHeader, line); |
| 161 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | filestreamHeader.close(); |
| 162 | |||
| 163 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | auto n = std::ranges::count(line, ','); |
| 164 | |||
| 165 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (n >= 3) |
| 166 | { | ||
| 167 | 1 | return FileType::ASCII; | |
| 168 | } | ||
| 169 | |||
| 170 | ✗ | return FileType::BINARY; | |
| 171 | 1 | } | |
| 172 | |||
| 173 | ✗ | LOG_ERROR("Could not open file {}", filepath.string()); | |
| 174 | ✗ | return FileType::NONE; | |
| 175 | 1 | } | |
| 176 | |||
| 177 | 3 | void NAV::FileReader::readHeader() | |
| 178 | { | ||
| 179 | LOG_TRACE("called"); | ||
| 180 | |||
| 181 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
|
3 | if (_fileType == FileType::ASCII) |
| 182 | { | ||
| 183 | 1 | _headerColumns.clear(); | |
| 184 | |||
| 185 | // Read header line | ||
| 186 | 1 | std::string line; | |
| 187 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | getline(line); |
| 188 | // Remove any starting non text characters | ||
| 189 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
|
2 | line.erase(line.begin(), std::ranges::find_if(line, [](int ch) { return std::isalnum(ch); })); |
| 190 | // Convert line into stream | ||
| 191 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | std::stringstream lineStream(line); |
| 192 | 1 | std::string cell; | |
| 193 | // Split line at comma | ||
| 194 |
4/6✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 13 times.
✓ Branch 7 taken 1 times.
|
14 | while (std::getline(lineStream, cell, ',')) |
| 195 | { | ||
| 196 | // Remove any trailing non text characters | ||
| 197 |
2/4✓ Branch 3 taken 13 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 13 times.
✗ Branch 8 not taken.
|
166 | cell.erase(std::ranges::find_if(cell, [](int ch) { return std::iscntrl(ch); }), cell.end()); |
| 198 |
1/2✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
|
13 | _headerColumns.push_back(cell); |
| 199 | } | ||
| 200 | 1 | } | |
| 201 | 3 | } | |
| 202 | |||
| 203 | 330 | void NAV::FileReader::resetReader() | |
| 204 | { | ||
| 205 | LOG_TRACE("called"); | ||
| 206 | |||
| 207 | // Return to position | ||
| 208 | 330 | _filestream.clear(); | |
| 209 | 330 | _filestream.seekg(_dataStart, std::ios_base::beg); | |
| 210 | 330 | _lineCnt = _lineCntDataStart; | |
| 211 | 330 | } | |
| 212 |