26#ifndef OPENSWMMVIS_UI_UTIL_EXTERNALCOLUMNFILECORE_H
27#define OPENSWMMVIS_UI_UTIL_EXTERNALCOLUMNFILECORE_H
41 std::size_t
a = 0,
b =
s.size();
42 auto space = [](
char c) {
43 return c ==
' ' || c ==
'\t' || c ==
'\r' || c ==
'\n';
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);
52inline std::vector<std::string>
splitCells(
const std::string& line,
char delim)
54 std::vector<std::string> out;
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);
67inline bool iequals(
const std::string&
a,
const std::string&
b)
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;
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)
84 if (!line.empty() && line.back() ==
'\r') line.pop_back();
90 for (
const char c : line) {
91 if (c ==
' ' || c ==
'\t')
continue;
92 return c ==
';' || c ==
'#';
101 static const std::string prefix =
"IDs:";
102 if (line.size() < prefix.size())
return false;
103 return iequals(line.substr(0, prefix.size()), prefix);
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;
125 if (tabs >= commas && tabs >= semis && tabs > 0)
return '\t';
126 if (semis > commas && semis > 0)
return ';';
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;
159 int y = 0, mo = 0, d = 0,
h = 0, mi = 0,
s = 0;
160 const char* c =
cell.c_str();
163 int n = std::sscanf(c,
"%d-%d-%d%*[ T]%d:%d:%d", &y, &mo, &d, &
h, &mi, &
s);
165 if (
n < 4) {
h = mi =
s = 0; }
166 else if (
n < 6) {
s = 0; }
167 out = {y, mo, d,
h, mi,
s};
172 n = std::sscanf(c,
"%d/%d/%d %d:%d:%d", &mo, &d, &y, &
h, &mi, &
s);
174 if (
n < 4) {
h = mi =
s = 0; }
175 else if (
n < 6) {
s = 0; }
180 if (meridiem == 2)
h += 12;
183 out = {y, mo, d,
h, mi,
s};
203 std::string& pathOut, std::string& columnOut)
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);
221 const std::string& column)
223 return column.empty() ?
path :
path +
":" + column;
229inline int findColumn(
const std::vector<std::string>& valueHeaders,
230 const std::string&
name)
232 for (std::size_t
i = 0;
i < valueHeaders.size(); ++
i)
233 if (
iequals(valueHeaders[
i],
name))
return static_cast<int>(
i);
249 return "col_" + std::to_string(oneBasedIndex);
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