From d1e04ec2c9134b3516940dfd765b088fc19b4429 Mon Sep 17 00:00:00 2001 From: Avril Date: Thu, 25 Jun 2020 01:34:04 +0100 Subject: [PATCH] initial commit --- .gitignore | 3 ++ Makefile | 12 +++++++ include/graphics.hpp | 15 ++++++++ include/hex.hpp | 8 +++++ include/memory-map.hpp | 80 ++++++++++++++++++++++++++++++++++++++++++ include/span.hpp | 75 +++++++++++++++++++++++++++++++++++++++ src/graphics.cpp | 23 ++++++++++++ src/hex.cpp | 38 ++++++++++++++++++++ src/main.cpp | 27 ++++++++++++++ src/memory-map.cpp | 38 ++++++++++++++++++++ 10 files changed, 319 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 include/graphics.hpp create mode 100644 include/hex.hpp create mode 100644 include/memory-map.hpp create mode 100644 include/span.hpp create mode 100644 src/graphics.cpp create mode 100644 src/hex.cpp create mode 100644 src/main.cpp create mode 100644 src/memory-map.cpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..df60db3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*~ +build/ +test.* diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ce9affe --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ +SRC:=src/*.cpp +INCLUDE:=include/ +BUILD:=build +CFLAGS:=-Wall -pedantic -O3 -march=native --std=gnu++20 +LFLAGS:=-ltickit -lfmt + +hexview: + g++ $(SRC) $(CFLAGS) -I$(INCLUDE) -o $(BUILD)/$@ $(LFLAGS) + strip $(BUILD)/$@ + +clean: + rm -f $(BUILD)/* diff --git a/include/graphics.hpp b/include/graphics.hpp new file mode 100644 index 0000000..75a0aac --- /dev/null +++ b/include/graphics.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include + +namespace gr +{ + struct Context + { + Context(); + ~Context(); + private: + struct _impl; + std::unique_ptr<_impl> impl; + }; +} diff --git a/include/hex.hpp b/include/hex.hpp new file mode 100644 index 0000000..50a2c2f --- /dev/null +++ b/include/hex.hpp @@ -0,0 +1,8 @@ +#pragma once + +#include "span.hpp" + +namespace hv { + /// Print a single screen + void print_screen(const span bytes, unsigned long offset); +} diff --git a/include/memory-map.hpp b/include/memory-map.hpp new file mode 100644 index 0000000..04ab367 --- /dev/null +++ b/include/memory-map.hpp @@ -0,0 +1,80 @@ +#pragma once + +#include +#include +#include "span.hpp" + +namespace hv +{ + typedef std::uint8_t byte; + struct memory_map + { + /// Create a copy-on-write memory map to a file descriptor + inline static memory_map cow(std::uint64_t size, int&& fd) noexcept + { + return memory_map(size, std::move(fd), true); + } + /// Create a copy-on-write memory map to a file by name + inline static memory_map cow(std::uint64_t size, const char* file) noexcept + { + return memory_map(size, file, true); + } + memory_map(std::uint64_t size, const char* const filename) noexcept; + memory_map(std::uint64_t size, int&& fd) noexcept; + ~memory_map(); + + inline byte& operator[](std::size_t index) + { + if (index>=size) throw "tried to index out of bounds of map"; + return ((byte*)block0)[index]; + } + inline const byte& operator[](std::size_t index) const + { + if (index>=size) throw "tried to index out of bounds of map"; + return ((byte*)block0)[index]; + } + + inline hv::span span() + { + return hv::span((byte*)block0, size); + } + + inline void* base() + { + return block0; + } + inline const void* base() const + { + return block0; + } + const bool is_cow; + const std::uint64_t size; + private: + memory_map(std::uint64_t size, int&& fd, bool _cow) noexcept; + memory_map(std::uint64_t size, const char* filename, bool _cow) noexcept; + const int fd; + void* const block0; + }; + + struct const_memory_map + { + const_memory_map(std::uint64_t size, const char* const filename) noexcept; + const_memory_map(std::uint64_t size, int&& fd) noexcept; + ~const_memory_map(); + + inline const byte& operator[](std::size_t index) const + { + if (index>=size) throw "tried to index out of bounds of map"; + return ((byte*)block0)[index]; + } + + inline const void* base() const + { + return block0; + } + const std::uint64_t size; + private: + const int fd; + const void* const block0; + }; +} diff --git a/include/span.hpp b/include/span.hpp new file mode 100644 index 0000000..397887c --- /dev/null +++ b/include/span.hpp @@ -0,0 +1,75 @@ +#pragma once + +#include +#include + +namespace hv +{ + /// A typed span of continuous memory with a bound. + template + struct span + { + inline span(T* ptr, std::size_t len) + : ptr(ptr),len(len){} + + inline operator T*() {return ptr;} + inline operator const T* const() {return ptr;} + inline T& operator*() {return *ptr;} + inline const T& operator*() const {return *ptr;} + + inline T& operator[](std::size_t index) + { + if (index>=len) throw "tried to index out of bounds of array"; + return ptr[index]; + } + inline const T& operator[](std::size_t index) const + { + if (index>=len) throw "tried to index out of bounds of array"; + return ptr[index]; + } + + inline span slice(std::size_t off, std::size_t len) + { + len = std::min(this->len, len); + if(len+off>=len || len < off) throw "tried to index out of bounds of array"; + return span(ptr+off, len-off); + } + inline span slice(std::size_t off) + { + if(len+off>=len || len < off) throw "tried to index out of bounds of array"; + + return span(ptr+off, len-off); + } + + template + inline span reinterpret() + { + return span((U*)ptr, size_bytes() / sizeof(U)); + } + + inline T* operator ->() + { + return ptr; + } + inline const T* operator ->() const + { + return ptr; + } + + inline T* raw() { + return ptr; + } + inline const T* raw() const { + return ptr; + } + inline std::size_t size() const { + return len; + } + inline std::size_t size_bytes() const { + return len * sizeof(T); + } + private: + T* const ptr; + std::size_t len; + }; +} diff --git a/src/graphics.cpp b/src/graphics.cpp new file mode 100644 index 0000000..4b01cbc --- /dev/null +++ b/src/graphics.cpp @@ -0,0 +1,23 @@ +#include + +#include + +namespace gr +{ + struct Context::_impl + { + Tickit* context; + }; + + Context::Context() + : impl(std::make_unique<_impl>()) + { + //TODO: Graphics. + //TODO: Change hex.cpp print_screen to use these graphics instead of stdout with fmt + } + + Context::~Context() + { + tickit_unref(impl->context); + } +} diff --git a/src/hex.cpp b/src/hex.cpp new file mode 100644 index 0000000..7f061fc --- /dev/null +++ b/src/hex.cpp @@ -0,0 +1,38 @@ +#include +#include + +const static constexpr char ascii_map[255] = { + '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', + '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', + '.', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', + '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', + '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', '.', + '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', + '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', + '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', + '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', + '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', + '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', + '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', + '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', +}; + +namespace hv { + void print_screen(const span memory, unsigned long offset) + { + fmt::print("0x{:016x} ", offset); + char ascii[17]; + ascii[16] = 0; + for(std::size_t i=0;i +#include +#include +#include +#include + +std::ifstream::pos_type filesize(const char* filename) +{ + std::ifstream in(filename, std::ifstream::ate | std::ifstream::binary); + return in.tellg(); +} + +inline auto map_file(const char* filename) +{ + return hv::memory_map(filesize(filename), filename); +} + +int main(void) +{ + auto map = map_file("test.txt"); + auto memory = map.span(); + + hv::print_screen(memory, 0); + fmt::print("\n"); + + return 0; +} diff --git a/src/memory-map.cpp b/src/memory-map.cpp new file mode 100644 index 0000000..40fac33 --- /dev/null +++ b/src/memory-map.cpp @@ -0,0 +1,38 @@ +#include +#include +#include + +#include + +namespace hv +{ + memory_map::memory_map(std::uint64_t size, int&& fd) noexcept + : is_cow(false), size(size), fd(fd), block0(mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) + { + if(!block0) throw "memory_map failed"; + } + memory_map::memory_map(std::uint64_t size, int&& fd, bool _cow) noexcept + : is_cow(true), size(size), fd(fd), block0(mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0)) + { + if(!block0) throw "memory_map::cow failed"; + } + memory_map::memory_map(std::uint64_t size, const char* file) noexcept + : memory_map(size, open(file, O_RDWR)) {} + memory_map::memory_map(std::uint64_t size, const char* file, bool _cow) noexcept + : memory_map(size, open(file, O_RDONLY), _cow) {} + memory_map::~memory_map() + { + munmap(block0, size); + close(fd); + } + + const_memory_map::const_memory_map(std::uint64_t size, int&& fd) noexcept + : size(size), fd(fd), block0(mmap(nullptr, size, PROT_READ, MAP_PRIVATE, fd, 0)) {} + const_memory_map::const_memory_map(std::uint64_t size, const char* file) noexcept + : const_memory_map(size, open(file, O_RDONLY)) {} + const_memory_map::~const_memory_map() + { + munmap(const_cast(block0), size); + close(fd); + } +}