#include "istakip_filtre.hpp" #include #include #include #include "fiko/istakip/model.hpp" #include "simdjson.h" namespace fiko { namespace { namespace sj = simdjson; using istakip::IsKayit; std::string alanDeger(const IsKayit& k, const std::string& ad) { const char* v = istakip::alanBul(k, ad.c_str()); return v ? v : ""; } std::string kucult(std::string s) { std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) { return std::tolower(c); }); return s; } // Her iki taraf da sayı olarak parse edilebiliyorsa sayısal, değilse metinsel // karşılaştırma (tarih alanları "YYYY-MM-DD" formatındaysa string sırası zaten // kronolojik sırayla örtüşür — ek bir tarih ayrıştırıcı gerektirmez). int karsilastir(const std::string& a, const std::string& b) { char* ea = nullptr; char* eb = nullptr; const double da = std::strtod(a.c_str(), &ea); const double db = std::strtod(b.c_str(), &eb); const bool sayisalA = ea != a.c_str() && *ea == '\0' && !a.empty(); const bool sayisalB = eb != b.c_str() && *eb == '\0' && !b.empty(); if (sayisalA && sayisalB) return (da < db) ? -1 : (da > db ? 1 : 0); const std::string la = kucult(a), lb = kucult(b); return la.compare(lb); } bool icinde(const std::string& hay, const std::string& needle) { if (needle.empty()) return true; const std::string lh = kucult(hay), ln = kucult(needle); return lh.find(ln) != std::string::npos; } std::string jsonKacir(const std::string& s) { std::string o; o.reserve(s.size() + 8); for (char c : s) { switch (c) { case '"': o += "\\\""; break; case '\\': o += "\\\\"; break; case '\n': o += "\\n"; break; case '\r': o += "\\r"; break; case '\t': o += "\\t"; break; default: o += c; } } return o; } } // namespace const std::vector& filtreOperatorleri() { static const std::vector ops = { FiltreOp::Esit, FiltreOp::Esitsiz, FiltreOp::Buyuk, FiltreOp::Kucuk, FiltreOp::BuyukEsit, FiltreOp::KucukEsit, FiltreOp::Icerir, FiltreOp::Icermez, FiltreOp::IleBaslar, FiltreOp::IleBiter, FiltreOp::Bos, FiltreOp::BosDegil, }; return ops; } const char* filtreOpEtiket(FiltreOp op) { switch (op) { case FiltreOp::Esit: return "="; case FiltreOp::Esitsiz: return "≠"; case FiltreOp::Buyuk: return ">"; case FiltreOp::Kucuk: return "<"; case FiltreOp::BuyukEsit: return "≥"; case FiltreOp::KucukEsit: return "≤"; case FiltreOp::Icerir: return "içerir"; case FiltreOp::Icermez: return "içermez"; case FiltreOp::IleBaslar: return "ile başlar"; case FiltreOp::IleBiter: return "ile biter"; case FiltreOp::Bos: return "boş"; case FiltreOp::BosDegil: return "boş değil"; } return "="; } const char* filtreOpKod(FiltreOp op) { switch (op) { case FiltreOp::Esit: return "esit"; case FiltreOp::Esitsiz: return "esitsiz"; case FiltreOp::Buyuk: return "buyuk"; case FiltreOp::Kucuk: return "kucuk"; case FiltreOp::BuyukEsit: return "buyuk_esit"; case FiltreOp::KucukEsit: return "kucuk_esit"; case FiltreOp::Icerir: return "icerir"; case FiltreOp::Icermez: return "icermez"; case FiltreOp::IleBaslar: return "ile_baslar"; case FiltreOp::IleBiter: return "ile_biter"; case FiltreOp::Bos: return "bos"; case FiltreOp::BosDegil: return "bos_degil"; } return "esit"; } FiltreOp filtreOpCoz(const std::string& kod) { for (FiltreOp op : filtreOperatorleri()) if (kod == filtreOpKod(op)) return op; return FiltreOp::Esit; } bool filtreOpDegerGerekir(FiltreOp op) { return op != FiltreOp::Bos && op != FiltreOp::BosDegil; } bool kosulGecer(const FiltreKosul& k, const IsKayit& kayit) { const std::string v = alanDeger(kayit, k.alan); switch (k.op) { case FiltreOp::Esit: return karsilastir(v, k.deger) == 0; case FiltreOp::Esitsiz: return karsilastir(v, k.deger) != 0; case FiltreOp::Buyuk: return karsilastir(v, k.deger) > 0; case FiltreOp::Kucuk: return karsilastir(v, k.deger) < 0; case FiltreOp::BuyukEsit: return karsilastir(v, k.deger) >= 0; case FiltreOp::KucukEsit: return karsilastir(v, k.deger) <= 0; case FiltreOp::Icerir: return icinde(v, k.deger); case FiltreOp::Icermez: return !icinde(v, k.deger); case FiltreOp::IleBaslar: { const std::string lv = kucult(v), ld = kucult(k.deger); return lv.size() >= ld.size() && lv.compare(0, ld.size(), ld) == 0; } case FiltreOp::IleBiter: { const std::string lv = kucult(v), ld = kucult(k.deger); return lv.size() >= ld.size() && lv.compare(lv.size() - ld.size(), ld.size(), ld) == 0; } case FiltreOp::Bos: return v.empty(); case FiltreOp::BosDegil: return !v.empty(); } return true; } bool filtreGecerMi(const FiltreGrup& g, const IsKayit& kayit) { if (g.kosullar.empty()) return true; if (g.mantik == "VEYA") { for (const auto& k : g.kosullar) if (kosulGecer(k, kayit)) return true; return false; } for (const auto& k : g.kosullar) if (!kosulGecer(k, kayit)) return false; return true; } std::string filtreSerialize(const FiltreGrup& g) { std::string j = "{\"mantik\":\"" + jsonKacir(g.mantik) + "\",\"kosullar\":["; for (size_t i = 0; i < g.kosullar.size(); ++i) { if (i) j += ","; const auto& k = g.kosullar[i]; j += "{\"alan\":\"" + jsonKacir(k.alan) + "\",\"op\":\"" + filtreOpKod(k.op) + "\",\"deger\":\"" + jsonKacir(k.deger) + "\"}"; } j += "]}"; return j; } FiltreGrup filtreCoz(const std::string& json) { FiltreGrup g; if (json.empty()) return g; sj::ondemand::parser parser; sj::padded_string dolu(json); sj::ondemand::document doc; if (parser.iterate(dolu).get(doc) != sj::SUCCESS) return g; sj::ondemand::object kok; if (doc.get_object().get(kok) != sj::SUCCESS) return g; std::string_view sv; if (kok["mantik"].get_string().get(sv) == sj::SUCCESS) g.mantik = std::string(sv); sj::ondemand::array arr; if (kok["kosullar"].get_array().get(arr) != sj::SUCCESS) return g; for (auto val : arr) { sj::ondemand::object o; if (val.get_object().get(o) != sj::SUCCESS) continue; FiltreKosul k; if (o["alan"].get_string().get(sv) == sj::SUCCESS) k.alan = std::string(sv); if (o["op"].get_string().get(sv) == sj::SUCCESS) k.op = filtreOpCoz(std::string(sv)); if (o["deger"].get_string().get(sv) == sj::SUCCESS) k.deger = std::string(sv); if (!k.alan.empty()) g.kosullar.push_back(std::move(k)); } return g; } } // namespace fiko