-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
65825d9
commit eb2ae7b
Showing
4 changed files
with
225 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,3 +27,5 @@ | |
*.exe | ||
*.out | ||
*.app | ||
|
||
build/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
cmake_minimum_required(VERSION 2.8.7) | ||
|
||
include_directories(${CMAKE_SOURCE_DIR}) | ||
|
||
#set(Boost_DEBUG 1) | ||
find_package( Boost REQUIRED ) | ||
if (Boost_FOUND) | ||
include_directories(BEFORE ${Boost_INCLUDE_DIR}) | ||
endif() | ||
|
||
set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -pedantic -Wextra -Wfatal-errors -Wno-unused-parameter -Wno-sign-compare") | ||
|
||
add_executable(tests tests.cpp) | ||
add_custom_target( | ||
tests.run | ||
COMMAND tests) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
#ifndef ASSERT_HASH_HPP_INCLUDE_GUARD | ||
#define ASSERT_HASH_HPP_INCLUDE_GUARD | ||
|
||
#include <climits> | ||
|
||
namespace assert_hash { | ||
|
||
using line_number_t = unsigned; | ||
|
||
namespace details { | ||
|
||
constexpr const char* end_of_string( const char* const str ) | ||
{ | ||
return *str == 0 | ||
? str | ||
: end_of_string( str + 1 ); | ||
} | ||
|
||
constexpr const char* file_base_impl( const char* const file, const char* const end_of_file, const unsigned directories ) | ||
{ | ||
return directories == 0 || end_of_file == file | ||
? end_of_file | ||
: ( *end_of_file == '\\' || *end_of_file == '/' | ||
? ( | ||
directories == 1 | ||
? end_of_file | ||
: file_base_impl( file, end_of_file - 1, directories - 1 ) | ||
) | ||
: file_base_impl( file, end_of_file - 1, directories ) | ||
); | ||
} | ||
|
||
template < typename T > | ||
struct check_checksum_type | ||
{ | ||
static_assert( std::is_integral< T >::value, "hash type must be integral" ); | ||
static_assert( std::is_unsigned< T >::value, "hash type must be unsigned" ); | ||
}; | ||
|
||
template < typename T > | ||
constexpr T add_char( const T value, const char* const file, unsigned exponent ) | ||
{ | ||
return value + ( *file << ( CHAR_BIT * exponent ) ); | ||
} | ||
|
||
template < typename T > | ||
constexpr unsigned next_exponent( unsigned exponent ) | ||
{ | ||
return exponent + 1 == sizeof( T ) | ||
? 0 | ||
: exponent + 1; | ||
} | ||
|
||
template < typename T > | ||
constexpr T file_hash_impl( const T value, const char* const file, unsigned exponent ) | ||
{ | ||
return *file == 0 | ||
? value | ||
: file_hash_impl( add_char< T >( value, file, exponent ), file + 1, next_exponent< T >( exponent ) ); | ||
} | ||
|
||
// to prevent "warning: shift count >= width of type [-Wshift-count-overflow]" | ||
template < typename T > | ||
constexpr line_number_t shift_line( const line_number_t line ) | ||
{ | ||
return sizeof( line ) <= sizeof( T ) | ||
? 0 | ||
: line >> ( CHAR_BIT * sizeof( T ) ); | ||
} | ||
|
||
template < typename T > | ||
constexpr T line_hash_impl( const T value, const line_number_t line ) | ||
{ | ||
return line == 0 | ||
? value | ||
: line_hash_impl< T >( value + static_cast< T >( line ), shift_line< T >( line ) ); | ||
} | ||
} | ||
|
||
constexpr const char* file_base( const char* const file, const unsigned directories = 0 ) | ||
{ | ||
return directories == 0 | ||
? file | ||
: details::file_base_impl( file, details::end_of_string( file ), directories ); | ||
} | ||
|
||
template < typename T > | ||
constexpr T file_hash( const char* const file ) | ||
{ | ||
return static_cast< void >( details::check_checksum_type< T >{} ), | ||
details::file_hash_impl< T >( 0, file, 0 ); | ||
} | ||
|
||
template < typename T > | ||
constexpr T line_hash( const line_number_t line ) | ||
{ | ||
return static_cast< void >( details::check_checksum_type< T >{} ), | ||
details::line_hash_impl< T >( 0 , line ); | ||
} | ||
|
||
template < typename T > | ||
constexpr T file_and_line_hash( const char* const file, const line_number_t line, const unsigned directories = 0 ) | ||
{ | ||
return file_hash< T >( file_base( file, directories ) ) + line_hash< T >( line ); | ||
} | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
#define BOOST_TEST_MODULE | ||
#include <boost/test/included/unit_test.hpp> | ||
|
||
#include <assert_hash.hpp> | ||
|
||
namespace ah = assert_hash; | ||
|
||
BOOST_AUTO_TEST_CASE( file_base_0 ) | ||
{ | ||
BOOST_CHECK_EQUAL( ah::file_base( "a" ), "a" ); | ||
BOOST_CHECK_EQUAL( ah::file_base( "a.txt" ), "a.txt" ); | ||
BOOST_CHECK_EQUAL( ah::file_base( ".a.txt" ), ".a.txt" ); | ||
BOOST_CHECK_EQUAL( ah::file_base( "c:\\asd\\.a.txt" ), "c:\\asd\\.a.txt" ); | ||
} | ||
|
||
BOOST_AUTO_TEST_CASE( end_of_string ) | ||
{ | ||
const char* const c = "asdasd"; | ||
BOOST_CHECK_EQUAL( ah::details::end_of_string( c ) - c, 6 ); | ||
BOOST_CHECK_EQUAL( ah::details::end_of_string( c + 6 ) - c, 6 ); | ||
} | ||
|
||
BOOST_AUTO_TEST_CASE( file_base_1 ) | ||
{ | ||
BOOST_CHECK_EQUAL( ah::file_base( "a", 1 ), "a" ); | ||
BOOST_CHECK_EQUAL( ah::file_base( "a.txt", 1 ), "a.txt" ); | ||
BOOST_CHECK_EQUAL( ah::file_base( ".a.txt", 1 ), ".a.txt" ); | ||
BOOST_CHECK_EQUAL( ah::file_base( "dev/null", 1 ), "/null" ); | ||
BOOST_CHECK_EQUAL( ah::file_base( "/Users/todi/assert_hash/build", 1 ), "/build" ); | ||
BOOST_CHECK_EQUAL( ah::file_base( "c:\\asda\\asdasd\\asd\\.a.txt", 1 ), "\\.a.txt" ); | ||
} | ||
|
||
BOOST_AUTO_TEST_CASE( file_base_2 ) | ||
{ | ||
BOOST_CHECK_EQUAL( ah::file_base( "a", 2 ), "a" ); | ||
BOOST_CHECK_EQUAL( ah::file_base( "a.txt", 2 ), "a.txt" ); | ||
BOOST_CHECK_EQUAL( ah::file_base( ".a.txt", 2 ), ".a.txt" ); | ||
BOOST_CHECK_EQUAL( ah::file_base( "dev/null", 2 ), "dev/null" ); | ||
BOOST_CHECK_EQUAL( ah::file_base( "/Users/todi/assert_hash/build", 2 ), "/assert_hash/build" ); | ||
BOOST_CHECK_EQUAL( ah::file_base( "c:\\asda\\asdasd\\asd\\.a.txt", 2 ), "\\asd\\.a.txt" ); | ||
} | ||
|
||
BOOST_AUTO_TEST_CASE( file_hash_16 ) | ||
{ | ||
BOOST_CHECK_EQUAL( ah::file_hash< std::uint16_t >( "" ), 0 ); | ||
BOOST_CHECK_EQUAL( ah::file_hash< std::uint16_t >( "a" ), 'a' ); | ||
BOOST_CHECK_EQUAL( ah::file_hash< std::uint16_t >( "ab" ), 'a' + ( 'b' << 8 ) ); | ||
BOOST_CHECK_EQUAL( ah::file_hash< std::uint16_t >( "abc" ), ( 'a' + ( 'b' << 8 ) + 'c' ) & 0xffff ); | ||
BOOST_CHECK_EQUAL( ah::file_hash< std::uint16_t >( "abcd" ), | ||
( 'a' + ( 'b' << 8 ) + 'c' + ( 'd' << 8 ) ) & 0xffff ); | ||
} | ||
|
||
BOOST_AUTO_TEST_CASE( file_hash_8 ) | ||
{ | ||
BOOST_CHECK_EQUAL( ah::file_hash< std::uint8_t >( "" ), 0 ); | ||
BOOST_CHECK_EQUAL( ah::file_hash< std::uint8_t >( "a" ), 'a' ); | ||
BOOST_CHECK_EQUAL( ah::file_hash< std::uint8_t >( "ab" ), 'a' + 'b' ); | ||
BOOST_CHECK_EQUAL( ah::file_hash< std::uint8_t >( "abc" ), ( 'a' + 'b' + 'c' ) & 0xff ); | ||
} | ||
|
||
BOOST_AUTO_TEST_CASE( line_hash_8 ) | ||
{ | ||
BOOST_CHECK_EQUAL( ah::line_hash< std::uint8_t >( 0 ), 0 ); | ||
BOOST_CHECK_EQUAL( ah::line_hash< std::uint8_t >( 0x12 ), 0x12 ); | ||
BOOST_CHECK_EQUAL( ah::line_hash< std::uint8_t >( 0x12345678 ), ( 0x78 + 0x56 + 0x34 + 0x12 ) & 0xff ); | ||
} | ||
|
||
BOOST_AUTO_TEST_CASE( line_hash_16 ) | ||
{ | ||
BOOST_CHECK_EQUAL( ah::line_hash< std::uint16_t >( 0 ), 0 ); | ||
BOOST_CHECK_EQUAL( ah::line_hash< std::uint16_t >( 0x12 ), 0x12 ); | ||
BOOST_CHECK_EQUAL( ah::line_hash< std::uint16_t >( 0x12345678 ), ( 0x5678 + 0x1234 ) & 0xffff ); | ||
} | ||
|
||
BOOST_AUTO_TEST_CASE( line_hash_32 ) | ||
{ | ||
BOOST_CHECK_EQUAL( ah::line_hash< std::uint32_t >( 0 ), 0 ); | ||
BOOST_CHECK_EQUAL( ah::line_hash< std::uint32_t >( 0x12 ), 0x12 ); | ||
BOOST_CHECK_EQUAL( ah::line_hash< std::uint32_t >( 0x12345678 ), 0x12345678 ); | ||
} | ||
|
||
BOOST_AUTO_TEST_CASE( file_and_line_hash ) | ||
{ | ||
constexpr std::uint16_t hash1 = ah::file_and_line_hash< std::uint16_t >( __FILE__, __LINE__ ); | ||
constexpr std::uint16_t hash2 = ah::file_and_line_hash< std::uint16_t >( __FILE__, __LINE__ ); | ||
|
||
BOOST_CHECK_NE( hash1, hash2 ); | ||
} | ||
|
||
template < const int > | ||
struct force_const {}; | ||
|
||
BOOST_AUTO_TEST_CASE( check_const_expr ) | ||
{ | ||
static constexpr const char* c = "test"; | ||
force_const< ah::file_base( c, 1 ) - c >(); | ||
force_const< ah::file_hash< unsigned >( c ) >(); | ||
force_const< ah::file_and_line_hash< std::uint16_t >( __FILE__, __LINE__ ) >(); | ||
} |