#pragma once #include #include // IWYU pragma: keep #include #include #include #include #include #include #include namespace ovdl { struct File { using buffer_ids = detail::TypeRegister< lexy::buffer, lexy::buffer, lexy::buffer, lexy::buffer, lexy::buffer, lexy::buffer>; File() = default; explicit File(const char* path); const char* path() const noexcept; bool is_valid() const noexcept; std::size_t size() const noexcept; template constexpr bool is_buffer() const { return buffer_ids::type_id>() + 1 == _buffer.index(); } template lexy::buffer* try_get_buffer_as() { return std::get_if>(&_buffer); } template const lexy::buffer* try_get_buffer_as() const { return std::get_if>(&_buffer); } template lexy::buffer& get_buffer_as() { assert((is_buffer())); return *std::get_if>(&_buffer); } template const lexy::buffer& get_buffer_as() const { assert((is_buffer())); return *std::get_if>(&_buffer); } #define SWITCH_LIST \ X(1) \ X(2) \ X(3) \ X(4) \ X(5) \ X(6) #define X(NUM) \ case NUM: \ return visitor(std::get(_buffer)); template decltype(auto) visit_buffer(Visitor&& visitor) { switch (_buffer.index()) { SWITCH_LIST case 0: return visitor(lexy::buffer<> {}); default: ovdl::detail::unreachable(); } } template Return visit_buffer(Visitor&& visitor) { switch (_buffer.index()) { SWITCH_LIST case 0: return visitor(lexy::buffer<> {}); default: ovdl::detail::unreachable(); } } template decltype(auto) visit_buffer(Visitor&& visitor) const { switch (_buffer.index()) { SWITCH_LIST case 0: return visitor(lexy::buffer<> {}); default: ovdl::detail::unreachable(); } } template Return visit_buffer(Visitor&& visitor) const { switch (_buffer.index()) { SWITCH_LIST case 0: return visitor(lexy::buffer<> {}); default: ovdl::detail::unreachable(); } } #undef X #undef SWITCH_LIST protected: const char* _path = ""; std::size_t _buffer_size = 0; detail::type_prepend_t _buffer; }; template struct BasicFile : File { using node_type = NodeT; BasicFile() = default; template explicit BasicFile(const char* path, lexy::buffer&& buffer) : File(path) { _buffer_size = buffer.size(); _buffer = static_cast&&>(buffer); } template explicit BasicFile(lexy::buffer&& buffer) : File("") { _buffer_size = buffer.size(); _buffer = static_cast&&>(buffer); } void set_location(const node_type* n, NodeLocation loc) { _map.insert(n, loc); } NodeLocation location_of(const node_type* n) const { auto result = _map.lookup(n); DRYAD_ASSERT(result != nullptr, "every Node should have a NodeLocation"); return *result; } protected: dryad::node_map _map; }; }