aboutsummaryrefslogtreecommitdiff
path: root/src/openvic-dataloader/File.hpp
blob: 90fcb11de1c823095741223ec52373ec0abb6183 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#pragma once

#include <cassert>
#include <concepts> // IWYU pragma: keep
#include <type_traits>
#include <variant>

#include <openvic-dataloader/NodeLocation.hpp>
#include <openvic-dataloader/detail/Utility.hpp>

#include <lexy/encoding.hpp>
#include <lexy/input/buffer.hpp>

#include <dryad/node_map.hpp>

namespace ovdl {
   struct File {
      using buffer_ids = detail::TypeRegister<
         lexy::buffer<lexy::default_encoding, void>,
         lexy::buffer<lexy::utf8_char_encoding, void>,
         lexy::buffer<lexy::utf8_encoding, void>,
         lexy::buffer<lexy::utf16_encoding, void>,
         lexy::buffer<lexy::utf32_encoding, void>,
         lexy::buffer<lexy::byte_encoding, void>>;

      explicit File(const char* path);

      const char* path() const noexcept;

      bool is_valid() const noexcept;

      template<typename Encoding, typename MemoryResource = void>
      constexpr bool is_buffer() const {
         return buffer_ids::type_id<lexy::buffer<Encoding, MemoryResource>>() + 1 == _buffer.index();
      }

      template<typename Encoding, typename MemoryResource = void>
      lexy::buffer<Encoding, MemoryResource>* try_get_buffer_as() {
         return std::get_if<lexy::buffer<Encoding, MemoryResource>>(&_buffer);
      }

      template<typename Encoding, typename MemoryResource = void>
      const lexy::buffer<Encoding, MemoryResource>* try_get_buffer_as() const {
         return std::get_if<lexy::buffer<Encoding, MemoryResource>>(&_buffer);
      }

      template<typename Encoding, typename MemoryResource = void>
      lexy::buffer<Encoding, MemoryResource>& get_buffer_as() {
         assert((is_buffer<Encoding, MemoryResource>()));
         return *std::get_if<lexy::buffer<Encoding, MemoryResource>>(&_buffer);
      }

      template<typename Encoding, typename MemoryResource = void>
      const lexy::buffer<Encoding, MemoryResource>& get_buffer_as() const {
         assert((is_buffer<Encoding, MemoryResource>()));
         return *std::get_if<lexy::buffer<Encoding, MemoryResource>>(&_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<NUM>(_buffer));

      template<typename Visitor>
      decltype(auto) visit_buffer(Visitor&& visitor) {
         switch (_buffer.index()) {
            SWITCH_LIST
            default: ovdl::detail::unreachable();
         }
      }

      template<typename Return, typename Visitor>
      Return visit_buffer(Visitor&& visitor) {
         switch (_buffer.index()) {
            SWITCH_LIST
            default: ovdl::detail::unreachable();
         }
      }

      template<typename Visitor>
      decltype(auto) visit_buffer(Visitor&& visitor) const {
         switch (_buffer.index()) {
            SWITCH_LIST
            default: ovdl::detail::unreachable();
         }
      }

      template<typename Return, typename Visitor>
      Return visit_buffer(Visitor&& visitor) const {
         switch (_buffer.index()) {
            SWITCH_LIST
            default: ovdl::detail::unreachable();
         }
      }
#undef X
#undef SWITCH_LIST

   protected:
      const char* _path;
      detail::type_prepend_t<buffer_ids::variant_type, std::monostate> _buffer;
   };

   template<typename NodeT>
   struct BasicFile : File {
      using node_type = NodeT;

      template<typename Encoding, typename MemoryResource = void>
      explicit BasicFile(const char* path, lexy::buffer<Encoding, MemoryResource>&& buffer)
         : File(path) {
         _buffer = static_cast<std::remove_reference_t<decltype(buffer)>&&>(buffer);
      }

      template<typename Encoding, typename MemoryResource = void>
      explicit BasicFile(lexy::buffer<Encoding, MemoryResource>&& buffer)
         : File("") {
         _buffer = static_cast<std::remove_reference_t<decltype(buffer)>&&>(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<const node_type, NodeLocation> _map;
   };
}