#include <chrono>
#include <cstdint>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
#include "dynamic_string.hpp"
#include "indexed_multivector.hpp"
#include "matcher/exact_match.hpp"
namespace ddwaf::matcher {
exact_match::exact_match(std::vector<std::string> &&data) : data_(std::move(data))
{
values_.reserve(data_.size());
for (const auto &str : data_) { values_.emplace(str, 0); }
}
exact_match::exact_match(const std::vector<std::pair<std::string, uint64_t>> &data)
{
data_.reserve(data.size());
values_.reserve(data.size());
for (const auto &[str, expiration] : data) {
const auto &ref = data_.emplace_back(str);
auto res = values_.emplace(ref, expiration);
if (!res.second) {
const uint64_t prev_expiration = res.first->second;
if (prev_expiration != 0 && (expiration == 0 || expiration > prev_expiration)) {
res.first->second = expiration;
}
}
}
}
exact_match::exact_match(
const indexed_multivector<std::string, std::pair<std::string, uint64_t>> &data)
{
data_.reserve(data.size());
values_.reserve(data.size());
for (const auto &[str, expiration] : data) {
const auto &ref = data_.emplace_back(str);
auto res = values_.emplace(ref, expiration);
if (!res.second) {
const uint64_t prev_expiration = res.first->second;
if (prev_expiration != 0 && (expiration == 0 || expiration > prev_expiration)) {
res.first->second = expiration;
}
}
}
}
std::pair<bool, dynamic_string> exact_match::match_impl(std::string_view str) const
{
if (values_.empty() || str.empty() || str.data() == nullptr) {
return {false, {}};
}
auto it = values_.find(str);
if (it == values_.end()) {
return {false, {}};
}
if (it->second > 0) {
const uint64_t now = std::chrono::duration_cast<std::chrono::seconds>(
std::chrono::system_clock::now().time_since_epoch())
.count();
if (it->second < now) {
return {false, {}};
}
}
return {true, std::string{str}};
}
}