4c04162e23
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
94 lines
2.7 KiB
C++
94 lines
2.7 KiB
C++
#include "data_table_logic.h"
|
|
|
|
#include <algorithm>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
|
|
namespace data_table {
|
|
|
|
const char* op_label(Op o) {
|
|
switch (o) {
|
|
case Op::Eq: return "=";
|
|
case Op::Neq: return "!=";
|
|
case Op::Gt: return ">";
|
|
case Op::Gte: return ">=";
|
|
case Op::Lt: return "<";
|
|
case Op::Lte: return "<=";
|
|
}
|
|
return "?";
|
|
}
|
|
|
|
bool parse_number(const char* s, double& out) {
|
|
if (!s || !*s) return false;
|
|
char* end = nullptr;
|
|
double v = std::strtod(s, &end);
|
|
if (end == s) return false;
|
|
while (*end == ' ' || *end == '\t') end++;
|
|
if (*end != '\0') return false;
|
|
out = v;
|
|
return true;
|
|
}
|
|
|
|
bool compare(const char* a, const char* b, Op op) {
|
|
if (!a) a = "";
|
|
if (!b) b = "";
|
|
double na, nb;
|
|
bool numeric = parse_number(a, na) && parse_number(b, nb);
|
|
if (numeric) {
|
|
switch (op) {
|
|
case Op::Eq: return na == nb;
|
|
case Op::Neq: return na != nb;
|
|
case Op::Gt: return na > nb;
|
|
case Op::Gte: return na >= nb;
|
|
case Op::Lt: return na < nb;
|
|
case Op::Lte: return na <= nb;
|
|
}
|
|
}
|
|
int c = std::strcmp(a, b);
|
|
switch (op) {
|
|
case Op::Eq: return c == 0;
|
|
case Op::Neq: return c != 0;
|
|
case Op::Gt: return c > 0;
|
|
case Op::Gte: return c >= 0;
|
|
case Op::Lt: return c < 0;
|
|
case Op::Lte: return c <= 0;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
std::vector<int> compute_visible_rows(const char* const* cells,
|
|
int rows, int cols,
|
|
const State& st)
|
|
{
|
|
std::vector<int> out;
|
|
out.reserve(rows);
|
|
for (int r = 0; r < rows; ++r) {
|
|
bool keep = true;
|
|
for (const auto& f : st.filters) {
|
|
if (f.col < 0 || f.col >= cols) continue;
|
|
const char* cell = cells[r * cols + f.col];
|
|
if (!compare(cell, f.value.c_str(), f.op)) { keep = false; break; }
|
|
}
|
|
if (keep) out.push_back(r);
|
|
}
|
|
if (st.sort_col >= 0 && st.sort_col < cols) {
|
|
int sc = st.sort_col;
|
|
bool desc = st.sort_desc;
|
|
std::sort(out.begin(), out.end(), [&](int a, int b) {
|
|
const char* ca = cells[a * cols + sc];
|
|
const char* cb = cells[b * cols + sc];
|
|
if (!ca) ca = "";
|
|
if (!cb) cb = "";
|
|
double na, nb;
|
|
bool num = parse_number(ca, na) && parse_number(cb, nb);
|
|
int cmp;
|
|
if (num) cmp = (na < nb) ? -1 : (na > nb ? 1 : 0);
|
|
else cmp = std::strcmp(ca, cb);
|
|
return desc ? (cmp > 0) : (cmp < 0);
|
|
});
|
|
}
|
|
return out;
|
|
}
|
|
|
|
} // namespace data_table
|