aboutsummaryrefslogtreecommitdiff
path: root/include/openvic-dataloader
diff options
context:
space:
mode:
Diffstat (limited to 'include/openvic-dataloader')
-rw-r--r--include/openvic-dataloader/csv/LineObject.hpp53
-rw-r--r--include/openvic-dataloader/csv/ValueNode.hpp81
2 files changed, 120 insertions, 14 deletions
diff --git a/include/openvic-dataloader/csv/LineObject.hpp b/include/openvic-dataloader/csv/LineObject.hpp
index c6d8e2a..b9ee9a5 100644
--- a/include/openvic-dataloader/csv/LineObject.hpp
+++ b/include/openvic-dataloader/csv/LineObject.hpp
@@ -4,7 +4,6 @@
#include <cctype>
#include <cstddef>
#include <cstdint>
-#include <functional>
#include <initializer_list>
#include <optional>
#include <ostream>
@@ -14,6 +13,7 @@
#include <utility>
#include <vector>
+#include <openvic-dataloader/csv/ValueNode.hpp>
#include <openvic-dataloader/detail/VectorConstexpr.hpp>
namespace ovdl::csv {
@@ -28,13 +28,13 @@ namespace ovdl::csv {
/// ;a;b;c -> 0,4+ == ""
///
/// If this is incorrect, please report an issue.
- class LineObject final : public std::vector<std::pair<std::uint32_t, std::string>> {
+ class LineObject final : public std::vector<ValueNode> {
public:
// Stored position of value
- using position_type = std::uint32_t;
+ using position_type = ValueNode::position_type;
// Value
- using inner_value_type = std::string;
- using container_type = std::vector<std::pair<position_type, inner_value_type>>;
+ using inner_value_type = ValueNode;
+ using container_type = std::vector<ValueNode>;
OVDL_VECTOR_CONSTEXPR LineObject() = default;
OVDL_VECTOR_CONSTEXPR LineObject(LineObject&) = default;
@@ -57,18 +57,42 @@ namespace ovdl::csv {
/// Special Functionality
/// Retrieves value, produces "" for empty values
- constexpr std::string_view get_value_for(std::size_t position) const {
+ constexpr std::string get_value_for(std::size_t position) const {
if (position < _prefix_end || position >= _suffix_end) return "";
- for (const auto& [pos, val] : *this) {
- if (pos == position) return val;
+ for (const auto& object : *this) {
+ if (object.get_position() == position) return object.make();
}
return "";
}
- /// Tries to retrieve reference, produces nullopt for empty values
- constexpr std::optional<const std::reference_wrapper<const std::string>> try_get_string_at(std::size_t position) const {
+ /// Tries to retrieve string, produces nullopt for empty values
+ constexpr std::optional<const std::string> try_get_string_at(std::size_t position) const {
if (position < _prefix_end || position >= _suffix_end) return std::nullopt;
- for (const auto& [pos, val] : *this) {
- if (pos == position) return std::cref(val);
+ for (const auto& object : *this) {
+ if (object.get_position() == position) return object.make();
+ }
+ return std::nullopt;
+ }
+ constexpr std::optional<const std::reference_wrapper<const ValueNode>> try_get_object_at(std::size_t position) const {
+ if (position < _prefix_end || position >= _suffix_end) return std::nullopt;
+ for (const auto& object : *this) {
+ if (object.get_position() == position) return object;
+ }
+ return std::nullopt;
+ }
+
+ /// Retrieves value, produces "" for empty values
+ constexpr std::string_view get_value_for(std::size_t position, const IsMap<std::string> auto& map) const {
+ if (position < _prefix_end || position >= _suffix_end) return "";
+ for (const auto& object : *this) {
+ if (object.get_position() == position) return object.make_from_map(map);
+ }
+ return "";
+ }
+ /// Tries to retrieve string, produces nullopt for empty values
+ constexpr std::optional<const std::string> try_get_string_at(std::size_t position, const IsMap<std::string> auto& map) const {
+ if (position < _prefix_end || position >= _suffix_end) return std::nullopt;
+ for (const auto& object : *this) {
+ if (object.get_position() == position) return object.make_from_map(map);
}
return std::nullopt;
}
@@ -91,8 +115,9 @@ namespace ovdl::csv {
inline std::ostream& operator<<(std::ostream& stream, const LineObject& line) {
static const char SEP = ';';
LineObject::position_type sep_index = 0;
- for (const auto& [pos, val] : line) {
- while (sep_index < pos) {
+ for (const auto& object : line) {
+ const std::string& val = object.make();
+ while (sep_index < object.get_position()) {
stream << SEP;
sep_index++;
}
diff --git a/include/openvic-dataloader/csv/ValueNode.hpp b/include/openvic-dataloader/csv/ValueNode.hpp
new file mode 100644
index 0000000..e66dac0
--- /dev/null
+++ b/include/openvic-dataloader/csv/ValueNode.hpp
@@ -0,0 +1,81 @@
+#pragma once
+
+#include <concepts>
+#include <cstdint>
+#include <initializer_list>
+#include <optional>
+#include <string>
+#include <string_view>
+#include <type_traits>
+#include <variant>
+#include <vector>
+
+#include <fmt/compile.h>
+#include <fmt/core.h>
+#include <fmt/format.h>
+
+namespace ovdl::csv {
+ template<typename T, typename Value>
+ concept IsMap =
+ requires(T t) {
+ { t.begin() } -> std::same_as<typename T::const_iterator>;
+ { t.end() } -> std::same_as<typename T::const_iterator>;
+ { t.empty() } -> std::same_as<bool>;
+ { t.size() } -> std::same_as<typename T::size_type>;
+ { t.at("") } -> std::same_as<const Value&>;
+ { t.find("") } -> std::same_as<typename T::const_iterator>;
+ { t[""] } -> std::same_as<const Value&>;
+ };
+
+ 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<std::string_view> suffix = std::nullopt) const {
+ return fmt::format(FMT_COMPILE("{}{}{}"), prefix, value, suffix.value_or(prefix));
+ }
+ };
+
+ using internal_value_type = std::variant<std::string, Placeholder>;
+ using position_type = std::uint32_t;
+
+ ValueNode();
+ ValueNode(std::string_view string, position_type position = 0);
+ ValueNode(std::vector<internal_value_type> value_list, position_type position = 0);
+ ValueNode(std::initializer_list<internal_value_type> 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;
+
+ inline std::string make_from_map(const IsMap<std::string> auto& map) const {
+ std::vector<std::string_view> 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<decltype(arg)>;
+ if constexpr (std::is_same_v<T, std::string>) {
+ return arg;
+ } else if constexpr (std::is_same_v<T, Placeholder>) {
+ 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<std::string_view> suffix = std::nullopt) const;
+
+ private:
+ position_type _position;
+ std::vector<internal_value_type> _value_list;
+ };
+} \ No newline at end of file