RESTinio
Loading...
Searching...
No Matches
sendfile_defs_default.hpp
Go to the documentation of this file.
1/*
2 restinio
3*/
4
5/*!
6 Sendfile routine definitions (default implementation via <cstdio>).
7
8 @since v.0.4.3
9*/
10
11#pragma once
12
13#include <cstdio>
14#include <cerrno>
15
16// for fixing #199 (https://github.com/Stiffstream/restinio/issues/199)
17// fopen_s seems to be defined in the global namespace.
18#include <stdio.h>
19
20namespace restinio
21{
22
23/** @name Aliases for sendfile operation.
24 */
25///@{
26using file_descriptor_t = std::FILE*;
29///@}
30
31
32/** @name File operations.
33 * @brief A minimal set of file operations.
34 *
35 * Incapsulates the details *cstdio* API for a set of file operations neccessary
36 * for sendfile_t class implementation.
37 */
38///@{
39
40//! Get file descriptor which stands for null.
41[[nodiscard]]
42constexpr file_descriptor_t null_file_descriptor(){ return nullptr; }
43
44//! Open file.
45/*!
46 * @note
47 * It uses `fopen_s` if the compiler is VC++.
48 *
49 * @note
50 * It's expected that @a file_path contains names in ANSI encoding
51 * on Windows platform.
52 */
53[[nodiscard]]
55open_file( const char * file_path )
56{
57//NOTE: fopen_s is only used for VC++ compiler.
58#if defined(_MSC_VER)
59 file_descriptor_t file_descriptor{};
60 const auto result = fopen_s( &file_descriptor, file_path, "rb" );
61
62 if( result )
63 {
64 const auto err_code = errno;
65 throw exception_t{
66 fmt::format(
67 RESTINIO_FMT_FORMAT_STRING( "fopen_s('{}') failed; errno={}" ),
68 file_path, err_code )
69 };
70 }
71
72 return file_descriptor;
73#else
74 file_descriptor_t file_descriptor = std::fopen( file_path, "rb" );
75
76 if( null_file_descriptor() == file_descriptor )
77 {
78 throw exception_t{
79 fmt::format(
80 RESTINIO_FMT_FORMAT_STRING( "std::fopen failed: '{}'" ),
81 file_path )
82 };
83 }
84
85 return file_descriptor;
86#endif
87}
88
89/*!
90 * @brief Helper function that accepts std::filesystem::path.
91 *
92 * @note
93 * It uses `_wfopen_s` if the compiler is VC++.
94 *
95 * @note
96 * It's expected that @a file_path contains names in ANSI encoding
97 * on Windows platform.
98 *
99 * @since v.0.7.1
100 */
101[[nodiscard]]
103open_file( const std::filesystem::path & file_path )
104{
105//NOTE: _wfopen_s is only used for VC++ compiler.
106#if defined(_MSC_VER)
107 file_descriptor_t file_descriptor{};
108 const auto result = _wfopen_s( &file_descriptor, file_path.c_str(), L"rb" );
109
110 if( result )
111 {
112 const auto err_code = errno;
113 throw exception_t{
114 fmt::format(
115 RESTINIO_FMT_FORMAT_STRING( "_wfopen_s failed; errno={}" ),
116 err_code )
117 };
118 }
119
120 return file_descriptor;
121#else
122 // Just delegate to ordinary open_file assuming that file_path is in UTF-8.
123 return open_file( file_path.c_str() );
124#endif
125}
126
127//! Get file size.
128template < typename META >
129[[nodiscard]]
130META
132{
133 file_size_t fsize = 0;
134
135 if( null_file_descriptor() != fd )
136 {
137 // Obtain file size:
138 if( 0 == std::fseek( fd , 0 , SEEK_END ) )
139 {
140 const auto end_pos = std::ftell( fd );
141
142 if( -1 != end_pos )
143 {
144 fsize = static_cast< file_size_t >( end_pos );
145 std::rewind( fd );
146 }
147 else
148 {
149 throw exception_t{ "std::ftell failed" };
150 }
151 }
152 else
153 {
154 throw exception_t{ "std::fseek failed" };
155 }
156 }
157
158 // No way to get last modification,
159 // Use current time instead.
160 return META{ fsize, std::chrono::system_clock::now() };
161}
162
163//! Close file by its descriptor.
164inline void
166{
167 std::fclose( fd );
168}
169///@}
170
171} /* namespace restinio */
constexpr file_descriptor_t null_file_descriptor()
Get file descriptor which stands for null.
void close_file(file_descriptor_t fd)
Close file by its descriptor.
file_descriptor_t open_file(const char *file_path)
Open file.
std::FILE * file_descriptor_t
file_descriptor_t open_file(const std::filesystem::path &file_path)
Helper function that accepts std::filesystem::path.
META get_file_meta(file_descriptor_t fd)
Get file size.