item_base.hpp (3640B)
1 #ifndef UUID_02043882_EC07_4CCA_BD13_1BB9F5C7DB9F 2 #define UUID_02043882_EC07_4CCA_BD13_1BB9F5C7DB9F 3 #pragma once 4 5 #include "../utils.hpp" 6 7 #include <libshit/assert.hpp> 8 #include <libshit/meta.hpp> 9 #include <libshit/shared_ptr.hpp> 10 #include <libshit/utils.hpp> 11 #include <libshit/container/intrusive.hpp> 12 #include <libshit/lua/dynamic_object.hpp> 13 #include <libshit/lua/function_call_types.hpp> 14 #include <libshit/lua/type_traits.hpp> 15 16 #include <cstdint> 17 #include <functional> 18 #include <boost/intrusive/set_hook.hpp> 19 20 namespace Neptools LIBSHIT_META("alias_file src/format/item.hpp") 21 { 22 23 class Item; 24 class Context; 25 26 struct ItemPointer 27 { 28 Item* item; 29 FilePosition offset; 30 31 ItemPointer(Item* item, FilePosition offset = 0) 32 : item{item}, offset{offset} {} 33 ItemPointer(Item& item, FilePosition offset = 0) 34 : item{&item}, offset{offset} {} 35 36 bool operator==(const ItemPointer& o) const 37 { return item == o.item && offset == o.offset; } 38 bool operator!=(const ItemPointer& o) const 39 { return item != o.item || offset != o.offset; } 40 41 Item& operator*() const { return *item; } 42 Item* operator->() const { return &*item; } 43 44 template <typename T> 45 T& As() const { return *Libshit::asserted_cast<T*>(item); } 46 47 template <typename T> 48 T& AsChecked() const { return dynamic_cast<T&>(*item); } 49 50 template <typename T> 51 T* Maybe() const { return dynamic_cast<T*>(item); } 52 53 template <typename T> 54 T& As0() const 55 { 56 LIBSHIT_ASSERT(offset == 0); 57 return *Libshit::asserted_cast<T*>(item); 58 } 59 60 template <typename T> 61 T& AsChecked0() const 62 { 63 LIBSHIT_ASSERT(offset == 0); 64 return dynamic_cast<T&>(*item); 65 } 66 67 template <typename T> 68 T* Maybe0() const 69 { 70 LIBSHIT_ASSERT(offset == 0); 71 return dynamic_cast<T*>(item); 72 } 73 }; 74 75 using LabelNameHook = boost::intrusive::set_base_hook< 76 boost::intrusive::tag<struct NameTag>, 77 boost::intrusive::optimize_size<true>, Libshit::LinkMode>; 78 using LabelOffsetHook = boost::intrusive::set_base_hook< 79 boost::intrusive::tag<struct OffsetTag>, 80 boost::intrusive::optimize_size<true>, Libshit::LinkMode>; 81 82 class Label final : 83 public Libshit::RefCounted, public Libshit::Lua::DynamicObject, 84 public LabelNameHook, public LabelOffsetHook 85 { 86 LIBSHIT_DYNAMIC_OBJECT; 87 public: 88 89 Label(std::string name, ItemPointer ptr) 90 : name{std::move(name)}, ptr{ptr} {} 91 92 const std::string& GetName() const { return name; } 93 const ItemPointer& GetPtr() const { return ptr; } 94 95 friend class Context; 96 friend class Item; 97 private: 98 std::string name; 99 ItemPointer ptr; 100 }; 101 102 using LabelPtr = Libshit::RefCountedPtr<Label>; 103 using WeakLabelPtr = Libshit::WeakRefCountedPtr<Label>; 104 105 // to be used by boost::intrusive::set 106 struct LabelKeyOfValue 107 { 108 using type = std::string; 109 const type& operator()(const Label& l) { return l.GetName(); } 110 }; 111 112 struct LabelOffsetKeyOfValue 113 { 114 using type = FilePosition; 115 const type& operator()(const Label& l) { return l.GetPtr().offset; } 116 }; 117 118 } 119 120 121 template<> struct Libshit::Lua::TupleLike<Neptools::ItemPointer> 122 { 123 template <size_t I> static auto& Get( 124 const Neptools::ItemPointer& ptr) noexcept 125 { 126 if constexpr (I == 0) return *ptr.item; 127 else if constexpr (I == 1) return ptr.offset; 128 } 129 static constexpr size_t SIZE = 2; 130 }; 131 132 template<> struct std::hash<::Neptools::ItemPointer> 133 { 134 std::size_t operator()(const ::Neptools::ItemPointer& ptr) const 135 { 136 return hash<::Neptools::Item*>()(ptr.item) ^ 137 hash<::Neptools::FilePosition>()(ptr.offset); 138 } 139 }; 140 141 #endif