diff --git a/include/daw/daw_cfile_ptr.h b/include/daw/daw_cfile_ptr.h new file mode 100644 index 000000000..4cd05c776 --- /dev/null +++ b/include/daw/daw_cfile_ptr.h @@ -0,0 +1,36 @@ +// Copyright (c) Darrell Wright +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/beached/header_libraries +// + +#pragma once + +#include "daw/daw_cpp_feature_check.h" +#include "daw/daw_restrict.h" +#include "daw/daw_string_view.h" +#include "daw/daw_unique_ptr.h" + +#include + +namespace daw { + namespace cfile_impl { + struct cfile_deleter { + cfile_deleter( ) = default; + + DAW_CPP23_STATIC_CALL_OP inline void + operator( )( std::FILE *fp ) DAW_CPP23_STATIC_CALL_OP_CONST noexcept { + std::fclose( fp ); + } + }; + } // namespace cfile_impl + + using unique_file_ptr = daw::unique_ptr; + + [[nodiscard]] inline unique_file_ptr + open_cfile( daw::string_view const path, char const *DAW_RESTRICT modes ) { + return unique_file_ptr( std::fopen( path.get_c_str( ).c_str( ), modes ) ); + } +} // namespace daw diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index a617263ec..02a19a61b 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -227,6 +227,7 @@ set( CPP20_NOT_MSVC_TEST_SOURCES set( NOT_MSVC_TEST_SOURCES daw_can_constant_evaluate_test.cpp + daw_cfile_ptr_test.cpp daw_parser_helper_test.cpp daw_piecewise_factory_test.cpp daw_tuple2_test.cpp @@ -257,7 +258,7 @@ target_compile_options( daw_test INTERFACE $<$:/permissive set( all_tests ${TEST_SOURCES} ) -if( NOT CMAKE_CXX_COMPILER_ID MATCHES "MSVC" ) +if( NOT MSVC ) list( APPEND all_tests ${NOT_MSVC_TEST_SOURCES} ) endif() @@ -265,6 +266,7 @@ foreach( CUR_TEST IN LISTS all_tests ) string( REPLACE ".cpp" "" CUR_TEST_NAME ${CUR_TEST} ) add_executable( "${CUR_TEST_NAME}" "${CUR_TEST}" ) target_link_libraries( ${CUR_TEST_NAME} PRIVATE daw_test ) + target_compile_features( ${CUR_TEST_NAME} PUBLIC cxx_std_17 ) add_test( ${CUR_TEST_NAME}_test ${CUR_TEST_NAME} ) add_dependencies( ${PROJECT_NAME}_full ${CUR_TEST_NAME} ) endforeach() @@ -284,6 +286,7 @@ foreach( CUR_TEST IN LISTS DEPRECATED_TEST_SOURCES ) else() add_executable( "${CUR_TEST_NAME}" EXCLUDE_FROM_ALL "deprecated/${CUR_TEST}" ) endif() + target_compile_features( ${CUR_TEST_NAME} PUBLIC cxx_std_17 ) target_link_libraries( ${CUR_TEST_NAME} PRIVATE daw_test ) endforeach() diff --git a/tests/daw_cfile_ptr_test.cpp b/tests/daw_cfile_ptr_test.cpp new file mode 100644 index 000000000..a3a279042 --- /dev/null +++ b/tests/daw_cfile_ptr_test.cpp @@ -0,0 +1,52 @@ +// Copyright (c) Darrell Wright +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/beached/header_libraries +// + +#include "daw/daw_cfile_ptr.h" +#include "daw/daw_ensure.h" + +#include +#include +#include +#include + +int main( int, char **argv ) { + static_assert( std::is_nothrow_destructible_v ); + static_assert( std::is_nothrow_move_constructible_v ); + static_assert( not std::is_copy_constructible_v ); + + auto const file_name = std::string( argv[0] ) + ".cfile_ptr_test"; + auto const path_storage = file_name + ".ignored"; + auto const path = daw::string_view( path_storage.data( ), file_name.size( ) ); + constexpr char contents[] = "daw::unique_file_ptr\n"; + + (void)std::remove( file_name.c_str( ) ); + daw_ensure( not daw::open_cfile( path, "rb" ) ); + + { + auto file = daw::open_cfile( path, "wb" ); + daw_ensure( file ); + auto moved_file = std::move( file ); + daw_ensure( not file ); + daw_ensure( moved_file ); + auto const count = + std::fwrite( contents, 1, sizeof( contents ) - 1, moved_file.get( ) ); + daw_ensure( count == sizeof( contents ) - 1 ); + } + + { + auto file = daw::open_cfile( path, "rb" ); + daw_ensure( file ); + auto buffer = std::string( sizeof( contents ) - 1, '\0' ); + auto const count = + std::fread( buffer.data( ), 1, buffer.size( ), file.get( ) ); + daw_ensure( count == buffer.size( ) ); + daw_ensure( buffer == contents ); + } + + daw_ensure( std::remove( file_name.c_str( ) ) == 0 ); +}