#pragma once #include #include #include #include #include #include #include #include #include #include namespace llo::utils { /// /// generates a random number of a specific type... /// /// type of number to generate... must be arithemtic... /// the minimum that can be generated... /// the maximum that can be generated... /// returns random arithemtic number... template < class number_t > number_t generate_random_number( const number_t minimum, const number_t maximum ) { static_assert( std::is_arithmetic_v< number_t >, "type is not arithmetic..." ); using uniform_distribution_t = std::conditional_t< std::is_integral_v< number_t >, std::uniform_int_distribution< number_t >, std::uniform_real_distribution< number_t > >; std::random_device random_device; auto mt = std::mt19937{ random_device() }; auto uniform_distribution = uniform_distribution_t{ minimum, maximum }; return uniform_distribution( mt ); } /// /// reads a binary file off disk into an std::vector... /// /// file path... /// vector to fill up with bytes... /// returns true if no errors happened... inline bool open_binary_file( std::string file, std::vector< uint8_t > &data ) { std::ifstream fstr( file, std::ios::binary ); if ( !fstr.is_open() ) return false; fstr.unsetf( std::ios::skipws ); fstr.seekg( 0, std::ios::end ); const auto file_size = fstr.tellg(); fstr.seekg( NULL, std::ios::beg ); data.reserve( static_cast< uint32_t >( file_size ) ); data.insert( data.begin(), std::istream_iterator< uint8_t >( fstr ), std::istream_iterator< uint8_t >() ); return true; } /// /// hash class, used in lloiff, symbols, sections, and much more... /// /// template < class T > class hash_t { std::size_t unique_hash, data_hash; const T data; public: /// /// hash constructor which generates the hash... /// /// data to be hashed... hash_t( const T &data ) : data{ data } { auto random_num = llo::utils::generate_random_number< std::uint64_t >( 0, std::numeric_limits< std::uint64_t >::max() ); this->unique_hash = std::hash< T >{}( data ) + std::hash< std::uint64_t >{}( random_num ); this->data_hash = std::hash< T >{}( data ); } /// /// makes a shared pointer containing the hash object... useful when chaining.... /// /// data to be hashed... /// shared pointer of the hash object.... static std::shared_ptr< hash_t > make( const T &data ) { return std::make_shared< hash_t >( data ); } /// /// returns a copy of the underlying data... /// /// returns a copy of the hashed data... T get_data() const { return data; } /// /// get the hash of the data... this hash is the same across each run... /// /// returns the constant hash value for the data... std::size_t get_hash() const { return data_hash; } /// /// returns a unique, per-runtime, per-object hash of the data... /// useful when there are multiple objects with the same data... /// /// returns the unique hash... std::size_t get_unique_hash() const { return unique_hash; } /// /// compares unique hashs... /// /// const reference of a hash... /// returns true if both unique hashes are the same... bool operator==( const hash_t< T > &hash ) { return hash.unique_hash == this->unique_hash; } }; } // namespace llo::utils