From 71b196531f5d52aaf2c0ee45cc902658f0d93a29 Mon Sep 17 00:00:00 2001 From: Darrell Wright Date: Sat, 3 Oct 2026 15:23:45 -0400 Subject: [PATCH] Refactor `read_file` and `read_wfile`: switch to `daw::string_view`, improve error handling, and ensure proper file closure. --- include/daw/daw_read_file.h | 70 +++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 31 deletions(-) diff --git a/include/daw/daw_read_file.h b/include/daw/daw_read_file.h index e5885746d..cc09495c8 100644 --- a/include/daw/daw_read_file.h +++ b/include/daw/daw_read_file.h @@ -8,9 +8,10 @@ #pragma once -#include "ciso646.h" -#include "daw_attributes.h" -#include "daw_traits.h" +#include "daw/ciso646.h" +#include "daw/daw_attributes.h" +#include "daw/daw_string_view.h" +#include "daw/daw_traits.h" #include #include @@ -19,45 +20,48 @@ #include #include #include +#include #include namespace daw { template DAW_ATTRIB_NOINLINE std::optional> - read_file( std::string const &path ) { + read_file( daw::string_view path ) { auto ec = std::error_code{ }; - auto const fsize = std::filesystem::file_size( path, ec ); + auto const fsize = + std::filesystem::file_size( std::string_view( path ), ec ); if( ec ) { return std::nullopt; } - if( fsize == 0 ) { - return std::basic_string{ }; + if( fsize % sizeof( CharT ) != 0 ) { + return std::nullopt; } + auto const element_count = fsize / sizeof( CharT ); if( static_cast( std::basic_string{ }.max_size( ) ) < - fsize ) { + element_count ) { // File is too big to fit into string(WIN32) return std::nullopt; } - auto result = - std::basic_string( static_cast( fsize ), CharT{ } ); + auto result = std::basic_string( + static_cast( element_count ), CharT{ } ); #if defined( _MSC_VER ) FILE *f = nullptr; - auto err = fopen_s( &f, path.c_str( ), "rb" ); - if( err ) { + auto err = fopen_s( &f, path.get_c_str( ).c_str( ), "rb" ); + if( err or not f ) { return std::nullopt; } #else - auto *f = fopen( path.c_str( ), "rb" ); + auto *f = fopen( path.get_c_str( ).c_str( ), "rb" ); if( not f ) { return std::nullopt; } #endif - auto num_read = fread( result.data( ), sizeof( CharT ), result.size( ), f ); - if( num_read != ( result.size( ) / sizeof( CharT ) ) ) { - fclose( f ); + auto const num_read = + fread( result.data( ), sizeof( CharT ), result.size( ), f ); + auto const close_result = fclose( f ); + if( num_read != result.size( ) or close_result != 0 ) { return std::nullopt; } - fclose( f ); return result; } @@ -65,49 +69,53 @@ namespace daw { inline constexpr auto terminate_on_read_file_error = terminate_on_read_file_error_t{ }; - inline std::string read_file( std::string const &path, + inline std::string read_file( daw::string_view path, terminate_on_read_file_error_t ) { auto result = read_file( path ); if( not result ) { std::cerr << "Error: could not open file '" << path << "'\n"; std::terminate( ); } - return *result; + return std::move( *result ); } #if defined( _MSC_VER ) DAW_ATTRIB_NOINLINE inline std::optional - read_wfile( std::wstring path ) { + read_wfile( daw::wstring_view path ) { using CharT = wchar_t; auto ec = std::error_code{ }; - auto const fsize = std::filesystem::file_size( path, ec ); + auto const fsize = + std::filesystem::file_size( std::wstring_view( path ), ec ); if( ec ) { return std::nullopt; } - if( fsize == 0 ) { - return std::basic_string{ }; + if( fsize % sizeof( CharT ) != 0 ) { + return std::nullopt; } + auto const element_count = fsize / sizeof( CharT ); if( static_cast( std::basic_string{ }.max_size( ) ) < - fsize ) { + element_count ) { // File is too big to fit into string(WIN32) return std::nullopt; } - auto result = - std::basic_string( static_cast( fsize ), CharT{ } ); + auto result = std::basic_string( + static_cast( element_count ), CharT{ } ); FILE *f = nullptr; - auto err = _wfopen_s( &f, path.c_str( ), L"rb" ); - if( err ) { + auto err = _wfopen_s( &f, path.get_c_str( ).c_str( ), L"rb" ); + if( err or not f ) { return std::nullopt; } - auto num_read = fread( result.data( ), sizeof( CharT ), result.size( ), f ); - if( num_read != ( result.size( ) / sizeof( CharT ) ) ) { + auto const num_read = + fread( result.data( ), sizeof( CharT ), result.size( ), f ); + auto const close_result = fclose( f ); + if( num_read != result.size( ) or close_result != 0 ) { return std::nullopt; } return result; } DAW_ATTRIB_NOINLINE inline std::wstring - read_wfile( std::wstring const &path, terminate_on_read_file_error_t ) { + read_wfile( daw::wstring_view path, terminate_on_read_file_error_t ) { auto result = read_wfile( path ); if( not result ) { std::wcerr << L"Error: could not open file '" << path << L'\n';