]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/leaf/example/print_file/print_file_result.cpp
1 // Copyright 2018-2022 Emil Dotchevski and Reverge Studios, Inc.
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 // This is the program presented in
7 // https://boostorg.github.io/leaf/#introduction-result.
9 // It reads a text file in a buffer and prints it to std::cout, using LEAF to
10 // handle errors. This version does not use exception handling. The version that
11 // does use exception handling is in print_file_eh.cpp.
13 #include <boost/leaf.hpp>
17 namespace leaf
= boost::leaf
;
20 // First, we need an enum to define our error codes:
33 using result
= leaf::result
<T
>;
36 // We will handle all failures in our main function, but first, here are the
37 // declarations of the functions it calls, each communicating failures using
40 // Parse the command line, return the file name.
41 result
<char const *> parse_command_line( int argc
, char const * argv
[] );
43 // Open a file for reading.
44 result
<std::shared_ptr
<FILE>> file_open( char const * file_name
);
46 // Return the size of the file.
47 result
<int> file_size( FILE & f
);
49 // Read size bytes from f into buf.
50 result
<void> file_read( FILE & f
, void * buf
, int size
);
53 // The main function, which handles all errors.
54 int main( int argc
, char const * argv
[] )
56 return leaf::try_handle_all(
60 BOOST_LEAF_AUTO(file_name
, parse_command_line(argc
,argv
));
62 auto load
= leaf::on_error( leaf::e_file_name
{file_name
} );
64 BOOST_LEAF_AUTO(f
, file_open(file_name
));
66 BOOST_LEAF_AUTO(s
, file_size(*f
));
68 std::string
buffer(1 + s
, '\0');
69 BOOST_LEAF_CHECK(file_read(*f
, &buffer
[0], buffer
.size()-1));
73 if( std::cout
.fail() )
74 return leaf::new_error(output_error
, leaf::e_errno
{errno
});
79 // Each of the lambdas below is an error handler. LEAF will consider
80 // them, in order, and call the first one that matches the available
83 // This handler will be called if the error includes:
84 // - an object of type error_code equal to open_error, and
85 // - an object of type leaf::e_errno that has .value equal to ENOENT,
87 // - an object of type leaf::e_file_name.
88 []( leaf::match
<error_code
, open_error
>, leaf::match_value
<leaf::e_errno
, ENOENT
>, leaf::e_file_name
const & fn
)
90 std::cerr
<< "File not found: " << fn
.value
<< std::endl
;
94 // This handler will be called if the error includes:
95 // - an object of type error_code equal to open_error, and
96 // - an object of type leaf::e_errno (regardless of its .value), and
97 // - an object of type leaf::e_file_name.
98 []( leaf::match
<error_code
, open_error
>, leaf::e_errno
const & errn
, leaf::e_file_name
const & fn
)
100 std::cerr
<< "Failed to open " << fn
.value
<< ", errno=" << errn
<< std::endl
;
104 // This handler will be called if the error includes:
105 // - an object of type error_code equal to any of size_error,
106 // read_error, eof_error, and
107 // - an optional object of type leaf::e_errno (regardless of its
109 // - an object of type leaf::e_file_name.
110 []( leaf::match
<error_code
, size_error
, read_error
, eof_error
>, leaf::e_errno
const * errn
, leaf::e_file_name
const & fn
)
112 std::cerr
<< "Failed to access " << fn
.value
;
114 std::cerr
<< ", errno=" << *errn
;
115 std::cerr
<< std::endl
;
119 // This handler will be called if the error includes:
120 // - an object of type error_code equal to output_error, and
121 // - an object of type leaf::e_errno (regardless of its .value),
122 []( leaf::match
<error_code
, output_error
>, leaf::e_errno
const & errn
)
124 std::cerr
<< "Output error, errno=" << errn
<< std::endl
;
128 // This handler will be called if we've got a bad_command_line
129 []( leaf::match
<error_code
, bad_command_line
> )
131 std::cout
<< "Bad command line argument" << std::endl
;
135 // This last handler matches any error: it prints diagnostic information
136 // to help debug logic errors in the program, since it failed to match
137 // an appropriate error handler to the error condition it encountered.
138 // In this program this handler will never be called.
139 []( leaf::error_info
const & unmatched
)
142 "Unknown failure detected" << std::endl
<<
143 "Cryptic diagnostic information follows" << std::endl
<<
150 // Implementations of the functions called by main:
153 // Parse the command line, return the file name.
154 result
<char const *> parse_command_line( int argc
, char const * argv
[] )
159 return leaf::new_error(bad_command_line
);
163 // Open a file for reading.
164 result
<std::shared_ptr
<FILE>> file_open( char const * file_name
)
166 if( FILE * f
= fopen(file_name
, "rb") )
167 return std::shared_ptr
<FILE>(f
, &fclose
);
169 return leaf::new_error(open_error
, leaf::e_errno
{errno
});
173 // Return the size of the file.
174 result
<int> file_size( FILE & f
)
176 auto load
= leaf::on_error([] { return leaf::e_errno
{errno
}; });
178 if( fseek(&f
, 0, SEEK_END
) )
179 return leaf::new_error(size_error
);
183 return leaf::new_error(size_error
);
185 if( fseek(&f
,0,SEEK_SET
) )
186 return leaf::new_error(size_error
);
192 // Read size bytes from f into buf.
193 result
<void> file_read( FILE & f
, void * buf
, int size
)
195 int n
= fread(buf
, 1, size
, &f
);
198 return leaf::new_error(read_error
, leaf::e_errno
{errno
});
201 return leaf::new_error(eof_error
);
206 ////////////////////////////////////////
208 #ifdef BOOST_LEAF_NO_EXCEPTIONS
212 BOOST_LEAF_NORETURN
void throw_exception( std::exception
const & e
)
214 std::cerr
<< "Terminating due to a C++ exception under BOOST_LEAF_NO_EXCEPTIONS: " << e
.what();
218 struct source_location
;
219 BOOST_LEAF_NORETURN
void throw_exception( std::exception
const & e
, boost::source_location
const & )