<commit_before>#pragma once
#include <cstdint>
#include <functional>
#include <array>
#include "io_registers.hpp"

namespace yagbe
{
	class memory
	{
	public:
		struct interceptor
		{
			using ReadCallback = std::function<uint8_t(memory &m, uint16_t)>;
			using WriteCallback = std::function<void(memory &m, uint16_t, uint8_t)>;

			ReadCallback  onRead;
			WriteCallback onWrite;
		};

		//TODO endianess
		union ByteWord
		{
			uint16_t word;
			uint8_t byte[2];
		};

		struct memory_address
		{
			memory_address(memory& m, uint16_t a) : _m(m), _a(a) 
			{
				_b = _m.read_at(_a);
			}

			~memory_address()
			{
				_m.write_byte_at(_a, _b);
			}

			memory_address& operator =(uint8_t b)
			{
				_b = b;
				return *this;
			}

			operator uint8_t() const
			{
				return _b;
			}


			memory_address& operator |=(uint8_t v)
			{
				_b |= v;
				return *this;
			}

			memory_address& operator &=(uint8_t v)
			{
				_b &= v;
				return *this;
			}

			memory_address& operator +=(uint8_t v)
			{
				_b += v;
				return *this;
			}

			memory_address& operator -=(uint8_t v)
			{
				_b -= v;
				return *this;
			}

			memory_address& operator >>=(uint8_t v)
			{
				_b >>= v;
				return *this;
			}

			memory_address& operator <<=(uint8_t v)
			{
				_b <<= v;
				return *this;
			}


		protected:
			memory& _m;
			uint16_t _a;
			uint8_t _b;
		};

		io_registers io_register{ data };

		memory_address at(uint16_t address)
		{
			return memory_address{*this, address};
		}

		//raw byte at address, without interceptors
		uint8_t& raw_at(uint16_t address)
		{
			return data[address];
		}

		uint8_t* raw_pointer_at(uint16_t address)
		{
			return data + address;
		}

		uint8_t read_at(uint16_t address)
		{
			auto& inter = interceptor_at(address).onRead;
			if (!inter)
				return data[address];
			return inter(*this, address);
		}

		void write_byte_at(uint16_t address, uint8_t byte)
		{
			auto& inter = interceptor_at(address).onWrite;
			if (!inter)
				data[address] = byte;
			else
				inter(*this, address, byte);
		}

		void write_word_at(uint16_t address, uint16_t word)
		{
			ByteWord w = { word };

			write_byte_at(address, w.byte[0]);
			write_byte_at(address + 1, w.byte[1]);
		}

		void map_interceptors(uint16_t start, uint16_t end, const interceptor::ReadCallback& rc, const interceptor::WriteCallback& wc)
		{
			end++;
			if (start % interceptor_range != 0)
				throw std::out_of_range("Wrong start");
			if (end % interceptor_range != 0)
				throw std::out_of_range("Wrong end");

			for (uint16_t i = start; i < end; i += interceptor_range)
			{
				auto& inter = interceptor_at(i);
				inter.onWrite = wc;
				inter.onRead = rc;
			}
		}

protected:
		interceptor& interceptor_at(uint16_t address)
		{
			auto index = address >> 8;
			return _interceptors[index];
		}

		constexpr static int interceptor_range = 0x100;
		std::array<interceptor, interceptor_range> _interceptors;
		uint8_t data[0xFFFF];
		

	};
};<commit_msg>- fixed interceptor registration<commit_after>#pragma once
#include <cstdint>
#include <functional>
#include <array>
#include "io_registers.hpp"

namespace yagbe
{
	class memory
	{
	public:
		struct interceptor
		{
			using ReadCallback = std::function<uint8_t(memory &m, uint16_t)>;
			using WriteCallback = std::function<void(memory &m, uint16_t, uint8_t)>;

			ReadCallback  onRead;
			WriteCallback onWrite;
		};

		//TODO endianess
		union ByteWord
		{
			uint16_t word;
			uint8_t byte[2];
		};

		struct memory_address
		{
			memory_address(memory& m, uint16_t a) : _m(m), _a(a) 
			{
				_b = _m.read_at(_a);
			}

			~memory_address()
			{
				_m.write_byte_at(_a, _b);
			}

			memory_address& operator =(uint8_t b)
			{
				_b = b;
				return *this;
			}

			operator uint8_t() const
			{
				return _b;
			}


			memory_address& operator |=(uint8_t v)
			{
				_b |= v;
				return *this;
			}

			memory_address& operator &=(uint8_t v)
			{
				_b &= v;
				return *this;
			}

			memory_address& operator +=(uint8_t v)
			{
				_b += v;
				return *this;
			}

			memory_address& operator -=(uint8_t v)
			{
				_b -= v;
				return *this;
			}

			memory_address& operator >>=(uint8_t v)
			{
				_b >>= v;
				return *this;
			}

			memory_address& operator <<=(uint8_t v)
			{
				_b <<= v;
				return *this;
			}


		protected:
			memory& _m;
			uint16_t _a;
			uint8_t _b;
		};

		io_registers io_register{ data };

		memory_address at(uint16_t address)
		{
			return memory_address{*this, address};
		}

		//raw byte at address, without interceptors
		uint8_t& raw_at(uint16_t address)
		{
			return data[address];
		}

		uint8_t* raw_pointer_at(uint16_t address)
		{
			return data + address;
		}

		uint8_t read_at(uint16_t address)
		{
			auto& inter = interceptor_at(address).onRead;
			if (!inter)
				return data[address];
			return inter(*this, address);
		}

		void write_byte_at(uint16_t address, uint8_t byte)
		{
			auto& inter = interceptor_at(address).onWrite;
			if (!inter)
				data[address] = byte;
			else
				inter(*this, address, byte);
		}

		void write_word_at(uint16_t address, uint16_t word)
		{
			ByteWord w = { word };

			write_byte_at(address, w.byte[0]);
			write_byte_at(address + 1, w.byte[1]);
		}

		void map_interceptors(uint16_t start, uint16_t end, const interceptor::ReadCallback& rc, const interceptor::WriteCallback& wc)
		{
			int end_range = end;
			end_range++;
			if (start % interceptor_range != 0)
				throw std::out_of_range("Wrong start");
			if (end_range % interceptor_range != 0)
				throw std::out_of_range("Wrong end");

			for (int i = start; i < end_range; i += interceptor_range)
			{
				auto& inter = interceptor_at(i);
				inter.onWrite = wc;
				inter.onRead = rc;
			}
		}

protected:
		interceptor& interceptor_at(uint16_t address)
		{
			auto index = address >> 8;
			return _interceptors[index];
		}

		constexpr static int interceptor_range = 0x100;
		std::array<interceptor, interceptor_range> _interceptors;
		uint8_t data[0xFFFF];
		

	};
};
{'fraction_non_alphanumeric': 0.12358238825883923, 'fraction_numerical': 0.0200133422281521, 'mean_word_length': 3.0194369973190347, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1248084', 'n_tokens_mistral': 2864, 'n_tokens_neox': 2285, 'n_words': 506}