| 
									
										
										
										
											2023-08-19 13:56:36 +02:00
										 |  |  | // Copyright 2020 Arthur Sonzogni. All rights reserved.
 | 
					
						
							|  |  |  | // Use of this source code is governed by the MIT license that can be found in
 | 
					
						
							|  |  |  | // the LICENSE file.
 | 
					
						
							| 
									
										
										
										
											2021-07-07 22:13:33 +02:00
										 |  |  | #ifndef FTXUI_UTIL_REF_HPP
 | 
					
						
							|  |  |  | #define FTXUI_UTIL_REF_HPP
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <ftxui/screen/string.hpp>
 | 
					
						
							| 
									
										
										
										
											2024-05-15 18:23:59 +02:00
										 |  |  | #include <memory>
 | 
					
						
							| 
									
										
										
										
											2021-07-07 22:13:33 +02:00
										 |  |  | #include <string>
 | 
					
						
							| 
									
										
										
										
											2023-08-12 15:18:33 -04:00
										 |  |  | #include <variant>
 | 
					
						
							| 
									
										
										
										
											2024-05-15 18:23:59 +02:00
										 |  |  | #include <vector>
 | 
					
						
							| 
									
										
										
										
											2021-07-07 22:13:33 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace ftxui { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-10 12:29:39 +02:00
										 |  |  | /// @brief An adapter. Own or reference an immutable object.
 | 
					
						
							| 
									
										
										
										
											2021-07-07 22:13:33 +02:00
										 |  |  | template <typename T> | 
					
						
							|  |  |  | class ConstRef { | 
					
						
							|  |  |  |  public: | 
					
						
							| 
									
										
										
										
											2023-08-12 15:18:33 -04:00
										 |  |  |   ConstRef() = default; | 
					
						
							| 
									
										
										
										
											2024-05-01 11:40:49 +02:00
										 |  |  |   ConstRef(T t) : variant_(std::move(t)) {}  // NOLINT
 | 
					
						
							|  |  |  |   ConstRef(const T* t) : variant_(t) {}      // NOLINT
 | 
					
						
							|  |  |  |   ConstRef& operator=(ConstRef&&) noexcept = default; | 
					
						
							| 
									
										
										
										
											2023-08-12 15:18:33 -04:00
										 |  |  |   ConstRef(const ConstRef<T>&) = default; | 
					
						
							| 
									
										
										
										
											2024-05-01 11:40:49 +02:00
										 |  |  |   ConstRef(ConstRef<T>&&) noexcept = default; | 
					
						
							|  |  |  |   ~ConstRef() = default; | 
					
						
							| 
									
										
										
										
											2023-08-12 15:18:33 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-19 05:10:29 -04:00
										 |  |  |   // Make a "reseatable" reference
 | 
					
						
							| 
									
										
										
										
											2023-08-12 15:18:33 -04:00
										 |  |  |   ConstRef<T>& operator=(const ConstRef<T>&) = default; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Accessors:
 | 
					
						
							|  |  |  |   const T& operator()() const { return *Address(); } | 
					
						
							|  |  |  |   const T& operator*() const { return *Address(); } | 
					
						
							|  |  |  |   const T* operator->() const { return Address(); } | 
					
						
							| 
									
										
										
										
											2021-07-07 22:13:33 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |  private: | 
					
						
							| 
									
										
										
										
											2023-08-12 15:18:33 -04:00
										 |  |  |   std::variant<T, const T*> variant_ = T{}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const T* Address() const { | 
					
						
							|  |  |  |     return std::holds_alternative<T>(variant_) ? &std::get<T>(variant_) | 
					
						
							|  |  |  |                                                : std::get<const T*>(variant_); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2021-07-07 22:13:33 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-10 12:29:39 +02:00
										 |  |  | /// @brief An adapter. Own or reference an mutable object.
 | 
					
						
							|  |  |  | template <typename T> | 
					
						
							| 
									
										
										
										
											2021-07-10 13:20:43 +02:00
										 |  |  | class Ref { | 
					
						
							| 
									
										
										
										
											2021-07-10 12:29:39 +02:00
										 |  |  |  public: | 
					
						
							| 
									
										
										
										
											2023-08-12 15:18:33 -04:00
										 |  |  |   Ref() = default; | 
					
						
							| 
									
										
										
										
											2024-05-01 11:40:49 +02:00
										 |  |  |   Ref(T t) : variant_(std::move(t)) {}  // NOLINT
 | 
					
						
							|  |  |  |   Ref(T* t) : variant_(t) {}            // NOLINT
 | 
					
						
							|  |  |  |   ~Ref() = default; | 
					
						
							|  |  |  |   Ref& operator=(Ref&&) noexcept = default; | 
					
						
							| 
									
										
										
										
											2023-08-12 15:18:33 -04:00
										 |  |  |   Ref(const Ref<T>&) = default; | 
					
						
							| 
									
										
										
										
											2024-05-01 11:40:49 +02:00
										 |  |  |   Ref(Ref<T>&&) noexcept = default; | 
					
						
							| 
									
										
										
										
											2023-08-12 15:18:33 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-19 05:10:29 -04:00
										 |  |  |   // Make a "reseatable" reference.
 | 
					
						
							| 
									
										
										
										
											2023-08-12 15:18:33 -04:00
										 |  |  |   Ref<T>& operator=(const Ref<T>&) = default; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Accessors:
 | 
					
						
							|  |  |  |   T& operator()() { return *Address(); } | 
					
						
							|  |  |  |   T& operator*() { return *Address(); } | 
					
						
							|  |  |  |   T* operator->() { return Address(); } | 
					
						
							|  |  |  |   const T& operator()() const { return *Address(); } | 
					
						
							|  |  |  |   const T& operator*() const { return *Address(); } | 
					
						
							|  |  |  |   const T* operator->() const { return Address(); } | 
					
						
							| 
									
										
										
										
											2021-07-10 12:29:39 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |  private: | 
					
						
							| 
									
										
										
										
											2023-08-12 15:18:33 -04:00
										 |  |  |   std::variant<T, T*> variant_ = T{}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const T* Address() const { | 
					
						
							|  |  |  |     return std::holds_alternative<T>(variant_) ? &std::get<T>(variant_) | 
					
						
							|  |  |  |                                                : std::get<T*>(variant_); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   T* Address() { | 
					
						
							|  |  |  |     return std::holds_alternative<T>(variant_) ? &std::get<T>(variant_) | 
					
						
							|  |  |  |                                                : std::get<T*>(variant_); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2021-07-10 12:29:39 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-10 11:50:17 +02:00
										 |  |  | /// @brief An adapter. Own or reference a constant string. For convenience, this
 | 
					
						
							|  |  |  | /// class convert multiple mutable string toward a shared representation.
 | 
					
						
							| 
									
										
										
										
											2023-08-12 15:18:33 -04:00
										 |  |  | class StringRef : public Ref<std::string> { | 
					
						
							| 
									
										
										
										
											2021-07-07 22:13:33 +02:00
										 |  |  |  public: | 
					
						
							| 
									
										
										
										
											2023-08-12 15:18:33 -04:00
										 |  |  |   using Ref<std::string>::Ref; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-01 11:40:49 +02:00
										 |  |  |   StringRef(const wchar_t* ref)  // NOLINT
 | 
					
						
							|  |  |  |       : StringRef(to_string(std::wstring(ref))) {} | 
					
						
							|  |  |  |   StringRef(const char* ref)  // NOLINT
 | 
					
						
							|  |  |  |       : StringRef(std::string(ref)) {} | 
					
						
							| 
									
										
										
										
											2021-08-08 23:25:20 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-10 11:50:17 +02:00
										 |  |  | /// @brief An adapter. Own or reference a constant string. For convenience, this
 | 
					
						
							|  |  |  | /// class convert multiple immutable string toward a shared representation.
 | 
					
						
							| 
									
										
										
										
											2023-08-12 15:18:33 -04:00
										 |  |  | class ConstStringRef : public ConstRef<std::string> { | 
					
						
							| 
									
										
										
										
											2021-07-07 22:13:33 +02:00
										 |  |  |  public: | 
					
						
							| 
									
										
										
										
											2023-08-12 15:18:33 -04:00
										 |  |  |   using ConstRef<std::string>::ConstRef; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-01 11:40:49 +02:00
										 |  |  |   ConstStringRef(const std::wstring* ref)  // NOLINT
 | 
					
						
							|  |  |  |       : ConstStringRef(to_string(*ref)) {} | 
					
						
							|  |  |  |   ConstStringRef(const std::wstring ref)  // NOLINT
 | 
					
						
							|  |  |  |       : ConstStringRef(to_string(ref)) {} | 
					
						
							|  |  |  |   ConstStringRef(const wchar_t* ref)  // NOLINT
 | 
					
						
							| 
									
										
										
										
											2023-08-12 15:18:33 -04:00
										 |  |  |       : ConstStringRef(to_string(std::wstring(ref))) {} | 
					
						
							| 
									
										
										
										
											2024-05-01 11:40:49 +02:00
										 |  |  |   ConstStringRef(const char* ref)  // NOLINT
 | 
					
						
							|  |  |  |       : ConstStringRef(std::string(ref)) {} | 
					
						
							| 
									
										
										
										
											2021-08-08 23:25:20 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /// @brief An adapter. Reference a list of strings.
 | 
					
						
							| 
									
										
										
										
											2024-05-15 18:23:59 +02:00
										 |  |  | ///
 | 
					
						
							|  |  |  | /// Supported input:
 | 
					
						
							|  |  |  | /// - `std::vector<std::string>`
 | 
					
						
							|  |  |  | /// - `std::vector<std::string>*`
 | 
					
						
							|  |  |  | /// - `std::vector<std::wstring>*`
 | 
					
						
							|  |  |  | /// - `Adapter*`
 | 
					
						
							|  |  |  | /// - `std::unique_ptr<Adapter>`
 | 
					
						
							| 
									
										
										
										
											2021-08-08 23:25:20 +02:00
										 |  |  | class ConstStringListRef { | 
					
						
							|  |  |  |  public: | 
					
						
							| 
									
										
										
										
											2024-05-15 18:23:59 +02:00
										 |  |  |   // Bring your own adapter:
 | 
					
						
							|  |  |  |   class Adapter { | 
					
						
							|  |  |  |    public: | 
					
						
							|  |  |  |     Adapter() = default; | 
					
						
							|  |  |  |     Adapter(const Adapter&) = default; | 
					
						
							|  |  |  |     Adapter& operator=(const Adapter&) = default; | 
					
						
							|  |  |  |     Adapter(Adapter&&) = default; | 
					
						
							|  |  |  |     Adapter& operator=(Adapter&&) = default; | 
					
						
							|  |  |  |     virtual ~Adapter() = default; | 
					
						
							|  |  |  |     virtual size_t size() const = 0; | 
					
						
							|  |  |  |     virtual std::string operator[](size_t i) const = 0; | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  |   using Variant = std::variant<const std::vector<std::string>,    //
 | 
					
						
							|  |  |  |                                const std::vector<std::string>*,   //
 | 
					
						
							|  |  |  |                                const std::vector<std::wstring>*,  //
 | 
					
						
							|  |  |  |                                Adapter*,                          //
 | 
					
						
							|  |  |  |                                std::unique_ptr<Adapter>           //
 | 
					
						
							|  |  |  |                                >; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-25 17:22:05 +02:00
										 |  |  |   ConstStringListRef() = default; | 
					
						
							| 
									
										
										
										
											2024-05-01 11:40:49 +02:00
										 |  |  |   ~ConstStringListRef() = default; | 
					
						
							| 
									
										
										
										
											2024-05-15 18:23:59 +02:00
										 |  |  |   ConstStringListRef& operator=(const ConstStringListRef&) = default; | 
					
						
							|  |  |  |   ConstStringListRef& operator=(ConstStringListRef&&) = default; | 
					
						
							|  |  |  |   ConstStringListRef(ConstStringListRef&&) = default; | 
					
						
							|  |  |  |   ConstStringListRef(const ConstStringListRef&) = default; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ConstStringListRef(std::vector<std::string> value)  // NOLINT
 | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     variant_ = std::make_shared<Variant>(value); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   ConstStringListRef(const std::vector<std::string>* value)  // NOLINT
 | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     variant_ = std::make_shared<Variant>(value); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   ConstStringListRef(const std::vector<std::wstring>* value)  // NOLINT
 | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     variant_ = std::make_shared<Variant>(value); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   ConstStringListRef(Adapter* adapter)  // NOLINT
 | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     variant_ = std::make_shared<Variant>(adapter); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   template <typename AdapterType> | 
					
						
							|  |  |  |   ConstStringListRef(std::unique_ptr<AdapterType> adapter)  // NOLINT
 | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     variant_ = std::make_shared<Variant>( | 
					
						
							|  |  |  |         static_cast<std::unique_ptr<Adapter>>(std::move(adapter))); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2021-08-08 23:25:20 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-25 17:22:05 +02:00
										 |  |  |   size_t size() const { | 
					
						
							| 
									
										
										
										
											2024-05-15 18:23:59 +02:00
										 |  |  |     return variant_ ? std::visit(SizeVisitor(), *variant_) : 0; | 
					
						
							| 
									
										
										
										
											2023-06-25 17:22:05 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-08 23:25:20 +02:00
										 |  |  |   std::string operator[](size_t i) const { | 
					
						
							| 
									
										
										
										
											2024-05-15 18:23:59 +02:00
										 |  |  |     return variant_ ? std::visit(IndexedGetter(i), *variant_) : ""; | 
					
						
							| 
									
										
										
										
											2021-08-08 23:25:20 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2021-07-07 22:13:33 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |  private: | 
					
						
							| 
									
										
										
										
											2024-05-15 18:23:59 +02:00
										 |  |  |   struct SizeVisitor { | 
					
						
							|  |  |  |     size_t operator()(const std::vector<std::string>& v) const { | 
					
						
							|  |  |  |       return v.size(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     size_t operator()(const std::vector<std::string>* v) const { | 
					
						
							|  |  |  |       return v->size(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     size_t operator()(const std::vector<std::wstring>* v) const { | 
					
						
							|  |  |  |       return v->size(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     size_t operator()(const Adapter* v) const { return v->size(); } | 
					
						
							|  |  |  |     size_t operator()(const std::unique_ptr<Adapter>& v) const { | 
					
						
							|  |  |  |       return v->size(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   struct IndexedGetter { | 
					
						
							|  |  |  |     IndexedGetter(size_t index)  // NOLINT
 | 
					
						
							|  |  |  |         : index_(index) {} | 
					
						
							|  |  |  |     size_t index_; | 
					
						
							|  |  |  |     std::string operator()(const std::vector<std::string>& v) const { | 
					
						
							|  |  |  |       return v[index_]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     std::string operator()(const std::vector<std::string>* v) const { | 
					
						
							|  |  |  |       return (*v)[index_]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     std::string operator()(const std::vector<std::wstring>* v) const { | 
					
						
							|  |  |  |       return to_string((*v)[index_]); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     std::string operator()(const Adapter* v) const { return (*v)[index_]; } | 
					
						
							|  |  |  |     std::string operator()(const std::unique_ptr<Adapter>& v) const { | 
					
						
							|  |  |  |       return (*v)[index_]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   std::shared_ptr<Variant> variant_; | 
					
						
							| 
									
										
										
										
											2021-07-07 22:13:33 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | }  // namespace ftxui
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif /* end of include guard: FTXUI_UTIL_REF_HPP */
 |