1 #ifndef XTENSOR_IO_DISK_HANDLER_HPP 2 #define XTENSOR_IO_DISK_HANDLER_HPP 3 4 #include <ghc/filesystem.hpp> 5 #include <xtensor/xarray.hpp> 6 #include <xtensor/xexpression.hpp> 7 #include "xio_stream_wrapper.hpp" 8 #include "xfile_array.hpp" 9 10 namespace fs = ghc::filesystem; 11 12 namespace xt 13 { 14 struct xio_disk_config 15 { 16 bool create_directories; 17 }; 18 19 template <class C> 20 class xio_disk_handler 21 { 22 public: 23 using io_config = xio_disk_config; 24 25 xio_disk_handler(); 26 27 template <class E> 28 void write(const xexpression<E>& expression, const std::string& path, xfile_dirty dirty); 29 30 template <class ET> 31 void read(ET& array, const std::string& path); 32 33 void configure(const C& format_config, const xio_disk_config& io_config); 34 void configure_io(const xio_disk_config& io_config); 35 36 private: 37 38 C m_format_config; 39 bool m_create_directories; 40 }; 41 42 template <class C> xio_disk_handler()43 xio_disk_handler<C>::xio_disk_handler() 44 : m_create_directories(true) 45 { 46 } 47 48 template <class C> 49 template <class E> write(const xexpression<E> & expression,const std::string & path,xfile_dirty dirty)50 inline void xio_disk_handler<C>::write(const xexpression<E>& expression, const std::string& path, xfile_dirty dirty) 51 { 52 if (m_format_config.will_dump(dirty)) 53 { 54 if (m_create_directories) 55 { 56 // maybe create directories 57 std::size_t i = path.rfind('/'); 58 if (i != std::string::npos) 59 { 60 fs::path directory = path.substr(0, i); 61 if (fs::exists(directory)) 62 { 63 if (!fs::is_directory(directory)) 64 { 65 XTENSOR_THROW(std::runtime_error, "Path is not a directory: " + std::string(directory)); 66 } 67 } 68 else 69 { 70 fs::create_directories(directory); 71 } 72 } 73 } 74 std::ofstream out_file(path, std::ofstream::binary); 75 if (out_file.is_open()) 76 { 77 auto s = xostream_wrapper(out_file); 78 dump_file(s, expression, m_format_config); 79 } 80 else 81 { 82 XTENSOR_THROW(std::runtime_error, "write: failed to open file " + path); 83 } 84 } 85 } 86 87 template <class C> 88 template <class ET> read(ET & array,const std::string & path)89 inline void xio_disk_handler<C>::read(ET& array, const std::string& path) 90 { 91 std::ifstream in_file(path, std::ifstream::binary); 92 if (in_file.is_open()) 93 { 94 auto s = xistream_wrapper(in_file); 95 load_file<ET>(s, array, m_format_config); 96 } 97 else 98 { 99 XTENSOR_THROW(std::runtime_error, "read: failed to open file " + path); 100 } 101 } 102 103 template <class C> configure(const C & format_config,const xio_disk_config & io_config)104 inline void xio_disk_handler<C>::configure(const C& format_config, const xio_disk_config& io_config) 105 { 106 m_format_config = format_config; 107 m_create_directories = io_config.create_directories; 108 } 109 110 template <class C> configure_io(const xio_disk_config & io_config)111 inline void xio_disk_handler<C>::configure_io(const xio_disk_config& io_config) 112 { 113 m_create_directories = io_config.create_directories; 114 } 115 116 } 117 118 #endif 119