#pragma once
#include <algorithm>
#include <array>
#include <cstddef>
#include <cstdint>
#include <functional>
#include <optional>
#include <span>
#include <string>
#include <string_view>
#include <utility>
#include <variant>
#include <vector>
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#define STRL(value) value, sizeof(value) - 1
template <typename T> using optional_ref = std::optional<std::reference_wrapper<T>>;
using scalar_type = std::variant<bool, int64_t, uint64_t, double, std::string>;
namespace ddwaf {
inline bool isalpha(char c) { return (static_cast<unsigned>(c) | 32) - 'a' < 26; }
inline bool isdigit(char c) { return static_cast<unsigned>(c) - '0' < 10; }
inline bool isxdigit(char c) { return isdigit(c) || ((unsigned)c | 32) - 'a' < 6; }
inline bool isspace(char c)
{
return c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v';
}
inline bool isupper(char c) { return static_cast<unsigned>(c) - 'A' < 26; }
inline bool islower(char c) { return static_cast<unsigned>(c) - 'a' < 26; }
inline bool isalnum(char c) { return isalpha(c) || isdigit(c); }
inline bool isboundary(char c) { return !isalnum(c) && c != '_'; }
inline char tolower(char c) { return isupper(c) ? static_cast<char>(c | 32) : c; }
inline uint8_t from_hex(char c)
{
auto uc = static_cast<uint8_t>(c);
return isdigit(c) ? (uc - '0') : ((uc | 32) - 'a' + 0xa);
}
template <class Fn> class defer {
public:
explicit defer(Fn &&fn) noexcept : fn_(std::move(fn)) {}
~defer() { fn_(); }
defer(const defer &) = delete;
defer(defer &&) = delete;
defer &operator=(const defer &) = delete;
defer &operator=(defer &&) = delete;
protected:
Fn fn_;
};
template <typename T> std::string to_string(T value);
template <typename T> std::pair<bool, T> from_string(std::string_view str);
std::vector<std::string_view> split(std::string_view str, char sep);
template <std::size_t N, std::size_t... I>
constexpr std::array<char, N> make_array(const char (&str)[N], std::index_sequence<I...>)
{
return std::array<char, N>{tolower(str[I])...};
}
template <std::size_t N>
constexpr bool string_iequals_literal(std::string_view left, const char (&right)[N])
{
return left.size() == (N - 1) && std::equal(left.begin(), left.end(),
make_array(right, std::make_index_sequence<N>()).begin(),
[](char l, char r) { return tolower(l) == r; });
}
bool string_iequals(std::string_view left, std::string_view right);
std::vector<std::variant<std::string_view, int64_t>> convert_key_path(
std::span<const std::variant<std::string, int64_t>> key_path);
}