Line data Source code
1 : /* Cam Mannett 2020 2 : * 3 : * See LICENSE file 4 : */ 5 : 6 : #include "malbolge/loader.hpp" 7 : 8 : #include <fstream> 9 : #include <iterator> 10 : #include <vector> 11 : 12 : using namespace malbolge; 13 : using namespace std::string_literals; 14 : 15 : namespace 16 : { 17 : using stream_iterator = std::istreambuf_iterator<char>; 18 : } 19 : 20 4 : std::ostream& malbolge::operator<<(std::ostream& stream, 21 : load_normalised_mode mode) 22 : { 23 4 : switch (mode) { 24 1 : case load_normalised_mode::AUTO: 25 1 : return stream << "AUTO"; 26 1 : case load_normalised_mode::ON: 27 1 : return stream << "ON"; 28 1 : case load_normalised_mode::OFF: 29 1 : return stream << "OFF"; 30 1 : default: 31 1 : return stream << "Unknown"; 32 : } 33 : } 34 : 35 28 : virtual_memory malbolge::load(const std::filesystem::path& path, 36 : load_normalised_mode mode) 37 : { 38 28 : log::print(log::INFO, "Loading file: ", path); 39 : 40 : try { 41 : // Unfortunately we cannot pass the istreambuf_iterators directly to 42 : // load_impl, as a range requires a ForwardIterator whilst 43 : // istreambuf_iterator is only an InputIterator. So we have to load 44 : // into an intermediary buffer first 45 28 : const auto file_size = std::filesystem::file_size(path); 46 27 : log::print(log::DEBUG, "File size: ", file_size); 47 : 48 54 : auto data = std::vector<char>{}; 49 27 : data.reserve(file_size); 50 : 51 : { 52 27 : auto stream = std::ifstream{}; 53 27 : stream.exceptions(std::ios::badbit | std::ios::failbit); 54 27 : stream.open(path, std::ios::binary); 55 : 56 27 : std::copy(stream_iterator{stream}, 57 27 : stream_iterator{}, 58 54 : std::back_inserter(data)); 59 : } 60 : 61 27 : log::print(log::INFO, "File loaded"); 62 : 63 47 : return load(data.begin(), data.end(), mode); 64 15 : } catch (parse_exception& e) { 65 7 : throw; 66 2 : } catch (std::exception& e) { 67 1 : throw parse_exception{"Failed to load program: "s + e.what()}; 68 : } 69 : } 70 : 71 7 : virtual_memory malbolge::load_from_cin(load_normalised_mode mode) 72 : { 73 7 : log::print(log::INFO, "Loading file from stdin"); 74 : 75 14 : auto program_data = ""s; 76 15 : for (auto line = ""s; std::getline(std::cin, line); ) { 77 8 : program_data += line; 78 : } 79 : 80 7 : log::print(log::INFO, "File loaded"); 81 : 82 9 : return load(std::begin(program_data), std::end(program_data), mode); 83 : }