SWMMVis  6.0.0-alpha.4
Qt6/C++ GIS-based graphical user interface for the SWMMVis engine (6.0.0-alpha.4)
Loading...
Searching...
No Matches
externalcolumnfilecore.h
Go to the documentation of this file.
1
26#ifndef OPENSWMMVIS_UI_UTIL_EXTERNALCOLUMNFILECORE_H
27#define OPENSWMMVIS_UI_UTIL_EXTERNALCOLUMNFILECORE_H
28
29#include <algorithm>
30#include <cctype>
31#include <cstdio>
32#include <string>
33#include <vector>
34
36
39inline std::string cellTrim(const std::string& s)
40{
41 std::size_t a = 0, b = s.size();
42 auto space = [](char c) {
43 return c == ' ' || c == '\t' || c == '\r' || c == '\n';
44 };
45 while (a < b && space(s[a])) ++a;
46 while (b > a && space(s[b - 1])) --b;
47 if (b - a >= 2 && s[a] == '"' && s[b - 1] == '"') { ++a; --b; }
48 return s.substr(a, b - a);
49}
50
52inline std::vector<std::string> splitCells(const std::string& line, char delim)
53{
54 std::vector<std::string> out;
55 std::string cur;
56 bool inQuotes = false;
57 for (const char c : line) {
58 if (c == '"') { inQuotes = !inQuotes; cur.push_back(c); }
59 else if (c == delim && !inQuotes) { out.push_back(cellTrim(cur)); cur.clear(); }
60 else cur.push_back(c);
61 }
62 out.push_back(cellTrim(cur));
63 return out;
64}
65
67inline bool iequals(const std::string& a, const std::string& b)
68{
69 if (a.size() != b.size()) return false;
70 for (std::size_t i = 0; i < a.size(); ++i)
71 if (std::tolower(static_cast<unsigned char>(a[i]))
72 != std::tolower(static_cast<unsigned char>(b[i]))) return false;
73 return true;
74}
75
77inline void normalizeLine(std::string& line, bool firstLine)
78{
79 if (firstLine && line.size() >= 3 &&
80 static_cast<unsigned char>(line[0]) == 0xEF &&
81 static_cast<unsigned char>(line[1]) == 0xBB &&
82 static_cast<unsigned char>(line[2]) == 0xBF)
83 line.erase(0, 3);
84 if (!line.empty() && line.back() == '\r') line.pop_back();
85}
86
88inline bool isBlankOrComment(const std::string& line)
89{
90 for (const char c : line) {
91 if (c == ' ' || c == '\t') continue;
92 return c == ';' || c == '#';
93 }
94 return true; // all-whitespace / empty
95}
96
99inline bool isTsfHeader(const std::string& line)
100{
101 static const std::string prefix = "IDs:";
102 if (line.size() < prefix.size()) return false;
103 return iequals(line.substr(0, prefix.size()), prefix);
104}
105
114inline char sniffDelimiter(const std::string& headerLine)
115{
116 long tabs = 0, commas = 0, semis = 0;
117 bool inQuotes = false;
118 for (const char c : headerLine) {
119 if (c == '"') { inQuotes = !inQuotes; continue; }
120 if (inQuotes) continue;
121 if (c == '\t') ++tabs;
122 else if (c == ',') ++commas;
123 else if (c == ';') ++semis;
124 }
125 if (tabs >= commas && tabs >= semis && tabs > 0) return '\t';
126 if (semis > commas && semis > 0) return ';';
127 return ',';
128}
129
132 int year = 0, month = 0, day = 0;
133 int hour = 0, minute = 0, second = 0;
134};
135
138inline int trailingMeridiem(const std::string& cell)
139{
140 const std::size_t e = cell.find_last_not_of(" \t\r\n");
141 if (e == std::string::npos || e < 1) return 0;
142 const char m1 = static_cast<char>(std::toupper(static_cast<unsigned char>(cell[e])));
143 const char m0 = static_cast<char>(std::toupper(static_cast<unsigned char>(cell[e - 1])));
144 if (m1 != 'M' || (m0 != 'A' && m0 != 'P')) return 0;
145 return m0 == 'A' ? 1 : 2;
146}
147
157inline bool parseSeriesDateTime(const std::string& cell, DateTimeParts& out)
158{
159 int y = 0, mo = 0, d = 0, h = 0, mi = 0, s = 0;
160 const char* c = cell.c_str();
161
162 // ISO-8601: YYYY-MM-DD[ T]HH:MM[:SS]
163 int n = std::sscanf(c, "%d-%d-%d%*[ T]%d:%d:%d", &y, &mo, &d, &h, &mi, &s);
164 if (n >= 3) {
165 if (n < 4) { h = mi = s = 0; }
166 else if (n < 6) { s = 0; }
167 out = {y, mo, d, h, mi, s};
168 return true;
169 }
170
171 // US: MM/DD/YYYY[ HH:MM[:SS]], optionally 12-hour with trailing AM/PM.
172 n = std::sscanf(c, "%d/%d/%d %d:%d:%d", &mo, &d, &y, &h, &mi, &s);
173 if (n >= 3) {
174 if (n < 4) { h = mi = s = 0; }
175 else if (n < 6) { s = 0; }
176 if (n >= 4) {
177 const int meridiem = trailingMeridiem(cell);
178 if (meridiem != 0) {
179 if (h == 12) h = 0; // 12:xx AM → 00:xx, 12:xx PM → 12:xx
180 if (meridiem == 2) h += 12; // PM
181 }
182 }
183 out = {y, mo, d, h, mi, s};
184 return true;
185 }
186 return false;
187}
188
202inline void splitPathColumn(const std::string& token,
203 std::string& pathOut, std::string& columnOut)
204{
205 const std::size_t colSep = token.rfind(':');
206 const bool driveLetter =
207 colSep == 1 && std::isalpha(static_cast<unsigned char>(token[0]));
208 if (colSep != std::string::npos && !driveLetter
209 && token.find_first_of("/\\", colSep + 1) == std::string::npos) {
210 pathOut = token.substr(0, colSep);
211 columnOut = token.substr(colSep + 1);
212 } else {
213 pathOut = token;
214 columnOut.clear();
215 }
216}
217
220inline std::string composePathColumn(const std::string& path,
221 const std::string& column)
222{
223 return column.empty() ? path : path + ":" + column;
224}
225
229inline int findColumn(const std::vector<std::string>& valueHeaders,
230 const std::string& name)
231{
232 for (std::size_t i = 0; i < valueHeaders.size(); ++i)
233 if (iequals(valueHeaders[i], name)) return static_cast<int>(i);
234 return -1;
235}
236
247inline std::string fabricatedColumnName(std::size_t oneBasedIndex)
248{
249 return "col_" + std::to_string(oneBasedIndex);
250}
251
252} // namespace openswmmvis::ui::extcol
253
254#endif // OPENSWMMVIS_UI_UTIL_EXTERNALCOLUMNFILECORE_H
size_t i
Definition contourjob.cpp:27
const char * token
Definition diagramspec.cpp:20
double s
Scene px per model length unit.
Definition inletdrawingview.cpp:82
int e
Definition inpmeshreader.cpp:41
int h
Definition mesh2dresultsexport.cpp:387
std::size_t n
Definition mesh2dresultsexport.cpp:426
std::vector< int > cell
Definition mesh2dresultsexport.cpp:609
int b
local residual indices, a < b
Definition meshquadmatch.cpp:46
int a
Definition meshquadmatch.cpp:46
Definition externalcolumnfilecore.h:35
bool isTsfHeader(const std::string &line)
True when the (normalized) line starts a PCSWMM .tsf header — case-insensitive "IDs:" prefix,...
Definition externalcolumnfilecore.h:99
void normalizeLine(std::string &line, bool firstLine)
Strip a UTF-8 BOM (first line only) and a trailing '\r'.
Definition externalcolumnfilecore.h:77
int findColumn(const std::vector< std::string > &valueHeaders, const std::string &name)
Resolve a column selector against a value-column name list (0-based, time column excluded)....
Definition externalcolumnfilecore.h:229
char sniffDelimiter(const std::string &headerLine)
Sniff the cell delimiter from the header row. The engine rule is "tab when tabs > 0 and tabs >= comma...
Definition externalcolumnfilecore.h:114
bool iequals(const std::string &a, const std::string &b)
Case-insensitive equality (engine csv_iequals).
Definition externalcolumnfilecore.h:67
std::vector< std::string > splitCells(const std::string &line, char delim)
Quote-aware split on a single-character delimiter (engine cell_split).
Definition externalcolumnfilecore.h:52
bool parseSeriesDateTime(const std::string &cell, DateTimeParts &out)
Parse a series timestamp cell into calendar components.
Definition externalcolumnfilecore.h:157
std::string cellTrim(const std::string &s)
Trim ASCII whitespace and one surrounding pair of double quotes. Mirrors the engine's cell_trim.
Definition externalcolumnfilecore.h:39
void splitPathColumn(const std::string &token, std::string &pathOut, std::string &columnOut)
Split a "path[:column]" token into its parts.
Definition externalcolumnfilecore.h:202
bool isBlankOrComment(const std::string &line)
True for empty/all-whitespace lines and ';'/'#' comment lines.
Definition externalcolumnfilecore.h:88
std::string composePathColumn(const std::string &path, const std::string &column)
Compose the "path:column" token (empty column → bare path). The GUI always builds this token itself —...
Definition externalcolumnfilecore.h:220
int trailingMeridiem(const std::string &cell)
0 = none, 1 = AM, 2 = PM — from the cell's trailing token (engine trailing_meridiem).
Definition externalcolumnfilecore.h:138
std::string fabricatedColumnName(std::size_t oneBasedIndex)
Display name the GUI shows for value column oneBasedIndex of a headerless file. Single definition of ...
Definition externalcolumnfilecore.h:247
int path
Definition pslgminsize.cpp:234
QString name
Definition sectionmodelbuilders.cpp:474
Calendar components produced by parseSeriesDateTime().
Definition externalcolumnfilecore.h:131
int year
Definition externalcolumnfilecore.h:132
int minute
Definition externalcolumnfilecore.h:133
int month
Definition externalcolumnfilecore.h:132
int day
Definition externalcolumnfilecore.h:132
int second
Definition externalcolumnfilecore.h:133
int hour
Definition externalcolumnfilecore.h:133