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 | 318 | std::filesystem::path NAV::FileReader::getFilepath() | |
45 | { | ||
46 | 318 | std::filesystem::path filepath{ _path }; | |
47 |
1/2✓ Branch 1 taken 318 times.
✗ Branch 2 not taken.
|
319 | if (filepath.is_relative()) |
48 | { | ||
49 |
1/2✓ Branch 1 taken 319 times.
✗ Branch 2 not taken.
|
318 | filepath = flow::GetInputPath(); |
50 |
1/2✓ Branch 1 taken 319 times.
✗ Branch 2 not taken.
|
319 | filepath /= _path; |
51 | } | ||
52 | 319 | 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 | 161 | void NAV::FileReader::restore(json const& j) | |
67 | { | ||
68 | LOG_TRACE("called"); | ||
69 | |||
70 |
1/2✓ Branch 1 taken 161 times.
✗ Branch 2 not taken.
|
161 | if (j.contains("path")) |
71 | { | ||
72 | 161 | j.at("path").get_to(_path); | |
73 | } | ||
74 | 161 | } | |
75 | |||
76 | 161 | bool NAV::FileReader::initialize() | |
77 | { | ||
78 |
1/2✓ Branch 1 taken 161 times.
✗ Branch 2 not taken.
|
161 | deinitialize(); |
79 | |||
80 | LOG_TRACE("called"); | ||
81 | |||
82 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 161 times.
|
161 | if (_path.empty()) |
83 | { | ||
84 | ✗ | return false; | |
85 | } | ||
86 | |||
87 |
1/2✓ Branch 1 taken 161 times.
✗ Branch 2 not taken.
|
161 | std::filesystem::path filepath = getFilepath(); |
88 | |||
89 |
2/4✓ Branch 1 taken 161 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 161 times.
|
161 | if (!std::filesystem::exists(filepath)) |
90 | { | ||
91 | ✗ | LOG_ERROR("File does not exist {}", filepath); | |
92 | ✗ | return false; | |
93 | } | ||
94 |
2/4✓ Branch 1 taken 160 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 160 times.
|
161 | 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 161 times.
✗ Branch 2 not taken.
|
160 | _fileType = determineFileType(); |
101 | |||
102 |
4/4✓ Branch 0 taken 8 times.
✓ Branch 1 taken 153 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 1 times.
|
161 | 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 160 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 160 times.
✗ Branch 6 not taken.
|
160 | _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 160 times.
|
160 | if (!_filestream.good()) |
113 | { | ||
114 | ✗ | LOG_ERROR("Could not open file {}", filepath); | |
115 | ✗ | return false; | |
116 | } | ||
117 | 160 | _lineCnt = 0; | |
118 | |||
119 |
1/2✓ Branch 1 taken 160 times.
✗ Branch 2 not taken.
|
160 | readHeader(); |
120 | |||
121 | 160 | _lineCntDataStart = _lineCnt; | |
122 |
1/2✓ Branch 1 taken 160 times.
✗ Branch 2 not taken.
|
160 | _dataStart = _filestream.tellg(); |
123 | |||
124 |
2/2✓ Branch 0 taken 153 times.
✓ Branch 1 taken 7 times.
|
160 | if (_fileType == FileType::ASCII) |
125 | { | ||
126 |
2/4✓ Branch 1 taken 153 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 153 times.
✗ Branch 7 not taken.
|
306 | 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 | 160 | return true; | |
134 | 161 | } | |
135 | |||
136 | 321 | void NAV::FileReader::deinitialize() | |
137 | { | ||
138 | LOG_TRACE("called"); | ||
139 | |||
140 | 321 | _headerColumns.clear(); | |
141 | |||
142 |
2/2✓ Branch 1 taken 160 times.
✓ Branch 2 taken 161 times.
|
321 | if (_filestream.is_open()) |
143 | { | ||
144 | 160 | _filestream.close(); | |
145 | } | ||
146 | |||
147 | 321 | _filestream.clear(); | |
148 | 321 | } | |
149 | |||
150 | ✗ | NAV::FileReader::FileType NAV::FileReader::determineFileType() | |
151 | { | ||
152 | LOG_TRACE("called"); | ||
153 | |||
154 | ✗ | auto filepath = getFilepath(); | |
155 | |||
156 | ✗ | auto filestreamHeader = std::ifstream(filepath); | |
157 | ✗ | if (_filestream.good()) | |
158 | { | ||
159 | ✗ | std::string line; | |
160 | ✗ | std::getline(filestreamHeader, line); | |
161 | ✗ | filestreamHeader.close(); | |
162 | |||
163 | ✗ | auto n = std::ranges::count(line, ','); | |
164 | |||
165 | ✗ | if (n >= 3) | |
166 | { | ||
167 | ✗ | return FileType::ASCII; | |
168 | } | ||
169 | |||
170 | ✗ | return FileType::BINARY; | |
171 | ✗ | } | |
172 | |||
173 | ✗ | LOG_ERROR("Could not open file {}", filepath.string()); | |
174 | ✗ | return FileType::NONE; | |
175 | ✗ | } | |
176 | |||
177 | 2 | void NAV::FileReader::readHeader() | |
178 | { | ||
179 | LOG_TRACE("called"); | ||
180 | |||
181 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (_fileType == FileType::ASCII) |
182 | { | ||
183 | ✗ | _headerColumns.clear(); | |
184 | |||
185 | // Read header line | ||
186 | ✗ | std::string line; | |
187 | ✗ | getline(line); | |
188 | // Remove any starting non text characters | ||
189 | ✗ | line.erase(line.begin(), std::ranges::find_if(line, [](int ch) { return std::isalnum(ch); })); | |
190 | // Convert line into stream | ||
191 | ✗ | std::stringstream lineStream(line); | |
192 | ✗ | std::string cell; | |
193 | // Split line at comma | ||
194 | ✗ | while (std::getline(lineStream, cell, ',')) | |
195 | { | ||
196 | // Remove any trailing non text characters | ||
197 | ✗ | cell.erase(std::ranges::find_if(cell, [](int ch) { return std::iscntrl(ch); }), cell.end()); | |
198 | ✗ | _headerColumns.push_back(cell); | |
199 | } | ||
200 | ✗ | } | |
201 | 2 | } | |
202 | |||
203 | 320 | void NAV::FileReader::resetReader() | |
204 | { | ||
205 | LOG_TRACE("called"); | ||
206 | |||
207 | // Return to position | ||
208 | 320 | _filestream.clear(); | |
209 | 320 | _filestream.seekg(_dataStart, std::ios_base::beg); | |
210 | 320 | _lineCnt = _lineCntDataStart; | |
211 | 320 | } | |
212 |