#pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include namespace ovdl::csv { template concept IsMap = requires(T t) { { t.begin() } -> std::same_as; { t.end() } -> std::same_as; { t.empty() } -> std::same_as; { t.size() } -> std::same_as; { t.at("") } -> std::same_as; { t.find("") } -> std::same_as; { t[""] } -> std::same_as; }; class ValueNode { public: struct Placeholder { static constexpr char ESCAPE_CHAR = '$'; static constexpr std::string_view ESCAPE_STR = std::string_view { &ESCAPE_CHAR, 1 }; std::string value; inline std::string as_string(std::string_view prefix = ESCAPE_STR, std::optional suffix = std::nullopt) const { return fmt::format(FMT_COMPILE("{}{}{}"), prefix, value, suffix.value_or(prefix)); } }; using internal_value_type = std::variant; using position_type = std::uint32_t; ValueNode(); ValueNode(std::string_view string, position_type position = 0); ValueNode(std::vector value_list, position_type position = 0); ValueNode(std::initializer_list value_list, position_type position = 0); void set_position(position_type position); position_type get_position() const; void set_as_list(internal_value_type value); void add_to_list(internal_value_type value); bool list_is_empty() const; OVDL_STRING_CONSTEXPR std::string make_from_map(const IsMap auto& map) const { std::vector pre_joined(_value_list.size()); for (auto&& value : _value_list) { pre_joined.push_back(std::visit([&](auto&& arg) -> std::string_view { using T = std::decay_t; if constexpr (std::is_same_v) { return arg; } else if constexpr (std::is_same_v) { return map[arg.value]; } }, value)); } return fmt::format(FMT_COMPILE("{}"), fmt::join(pre_joined, "")); } std::string make(std::string_view prefix = Placeholder::ESCAPE_STR, std::optional suffix = std::nullopt) const; private: position_type _position; std::vector _value_list; }; }