From c66d1f5c0af70161f4ad4c4175f4280e95b55dfd Mon Sep 17 00:00:00 2001 From: Dennis Brentjes Date: Sun, 19 Jun 2016 11:58:16 +0200 Subject: Initial commit of a mz-header parser. --- mz/mz_header.cpp | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 mz/mz_header.cpp (limited to 'mz/mz_header.cpp') diff --git a/mz/mz_header.cpp b/mz/mz_header.cpp new file mode 100644 index 0000000..e6d4461 --- /dev/null +++ b/mz/mz_header.cpp @@ -0,0 +1,116 @@ +#include "mz_header.hpp" +#include "index_list.hpp" + +#include +#include + +#include +#include + +UnexpectedEOS::UnexpectedEOS() +: std::runtime_error("Unexpected end of stream.") +{} + +UnexpectedEOS::UnexpectedEOS(std::__cxx11::string location) +: std::runtime_error("Unexpected end of stream after " + location) +{} + +NotAMZFileException::NotAMZFileException() +: std::runtime_error("This stream does not contain a valid MZ executable") +{} + +BOOST_FUSION_ADAPT_STRUCT( + MZHeader, + (Magic, magic) + (uint16_t, bytes_in_last_block) + (uint16_t, blocks_in_file) + (uint16_t, num_relocs) + (uint16_t, header_paragraphs) + (uint16_t, min_extra_paragraphs) + (uint16_t, max_extra_paragraphs) + (uint16_t, ss) + (uint16_t, sp) + (uint16_t, checksum) + (uint16_t, ip) + (uint16_t, cs) + (uint16_t, reloc_table_offset) + (uint16_t, overlay_number) +) + +template +T parse(std::istream& is, std::string name); + +template<> +uint16_t parse(std::istream& is, std::string name) { + if(!is) { + throw UnexpectedEOS(); + } + char data[2] = {0, 0}; + is.read(data, 2); + if(!is) { + throw UnexpectedEOS(name); + } + + return (((unsigned char) data[1]) << 8) | (unsigned char) data[0]; +} + +template<> +Magic parse(std::istream& is, std::string name) { + if(!is) { + throw UnexpectedEOS(); + } + char data[2]; + is.read(data, 2); + if(!is) { + throw UnexpectedEOS(name); + } + + return static_cast((data[1] << 8) | data[0]); +} + +template +MZHeader parse_mz_file_impl(std::istream& is, indices) { + + return {parse::type>::type>(is, boost::fusion::extension::struct_member_name::call())...}; + +} + +MZHeader parse_mz_file(std::istream& is) { + + typedef build_indices::value>::type indices; + + return parse_mz_file_impl(is, indices{}); +} + +std::ostream& output_impl(std::ostream& os, MZHeader const&, indices<>) { + return os; +} + +template +std::ostream& output(std::ostream& os, T rh) { + return os << std::hex << std::setw(sizeof(T) * 2) << std::setfill('0') << rh << std::endl; +} + +std::string to_string(Magic magic) { + char* c = reinterpret_cast(&magic); + return std::string(c, sizeof(Magic)); +} + +template <> +std::ostream& output(std::ostream& os, Magic m) { + return os << std::hex << std::setw(4) << std::setfill('0') << m << " (" << to_string(m) << ")" << std::endl; +} + +template +std::ostream& output_impl(std::ostream& os, const MZHeader& header, indices) { + os << boost::fusion::extension::struct_member_name::call() << ": "; + output(os, boost::fusion::at_c(header)); + return output_impl(os, header, indices{}); +} + +std::ostream& operator<<(std::ostream& os, MZHeader const& header) +{ + typedef build_indices::value>::type indices; + + return output_impl(os, header, indices{}); +} -- cgit v1.2.3-70-g09d2