1//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc.
2
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)
5
6//This program simulates errors on copying simple data files. It demonstrates
7//typical Boost Exception usage.
8
9//The output from this program can vary depending on the platform.
10
11#include <boost/throw_exception.hpp>
12#include <boost/exception/info.hpp>
13#include <boost/exception/get_error_info.hpp>
14#include <boost/exception/diagnostic_information.hpp>
15#include <boost/exception/errinfo_file_open_mode.hpp>
16#include <boost/exception/errinfo_file_handle.hpp>
17#include <boost/exception/errinfo_file_name.hpp>
18#include <boost/exception/errinfo_api_function.hpp>
19#include <boost/exception/errinfo_errno.hpp>
20#include <boost/shared_ptr.hpp>
21#include <boost/weak_ptr.hpp>
22#include <iostream>
23
24typedef boost::error_info<struct tag_file_name_src,std::string> errinfo_src_file_name;
25typedef boost::error_info<struct tag_file_name_dst,std::string> errinfo_dst_file_name;
26
27char const data[] = "example";
28size_t const data_size = sizeof(data);
29
30class
31error: //Base for all exception objects we throw.
32 public virtual std::exception,
33 public virtual boost::exception
34 {
35 public:
36
37 char const *
38 what() const BOOST_NOEXCEPT_OR_NOTHROW
39 {
40 return "example_io error";
41 }
42
43 protected:
44
45 ~error() BOOST_NOEXCEPT_OR_NOTHROW
46 {
47 }
48 };
49
50struct open_error: virtual error { };
51struct read_error: virtual error { };
52struct write_error: virtual error { };
53struct fopen_error: virtual open_error { };
54struct fread_error: virtual read_error { };
55struct fwrite_error: virtual write_error { };
56
57boost::shared_ptr<FILE>
58my_fopen( char const * name, char const * mode )
59 {
60 if( FILE * f = ::fopen(filename: name,modes: mode) )
61 return boost::shared_ptr<FILE>(f,fclose);
62 else
63 BOOST_THROW_EXCEPTION(fopen_error() <<
64 boost::errinfo_errno (errno) <<
65 boost::errinfo_file_name(name) <<
66 boost::errinfo_file_open_mode(mode) <<
67 boost::errinfo_api_function("fopen"));
68 }
69
70void
71my_fread( void * buffer, size_t size, size_t count, boost::shared_ptr<FILE> const & stream )
72 {
73 assert(stream);
74 if( count!=fread(ptr: buffer,size: size,n: count,stream: stream.get()) || ferror(stream: stream.get()) )
75 BOOST_THROW_EXCEPTION(fread_error() <<
76 boost::errinfo_api_function("fread") <<
77 boost::errinfo_errno(errno) <<
78 boost::errinfo_file_handle(boost::weak_ptr<FILE>(stream)));
79 }
80
81void
82my_fwrite( void const * buffer, size_t size, size_t count, boost::shared_ptr<FILE> const & stream )
83 {
84 assert(stream);
85 if( count!=fwrite(ptr: buffer,size: size,n: count,s: stream.get()) || ferror(stream: stream.get()) )
86 BOOST_THROW_EXCEPTION(fwrite_error() <<
87 boost::errinfo_api_function("fwrite") <<
88 boost::errinfo_errno(errno) <<
89 boost::errinfo_file_handle(boost::weak_ptr<FILE>(stream)));
90 }
91
92void
93reset_file( char const * file_name )
94 {
95 (void) my_fopen(name: file_name,mode: "wb");
96 }
97
98void
99create_data( char const * file_name )
100 {
101 boost::shared_ptr<FILE> f = my_fopen(name: file_name,mode: "wb");
102 my_fwrite( buffer: data, size: 1, count: data_size, stream: f );
103 }
104
105void
106copy_data( char const * src_file_name, char const * dst_file_name )
107 {
108 boost::shared_ptr<FILE> src = my_fopen(name: src_file_name,mode: "rb");
109 boost::shared_ptr<FILE> dst = my_fopen(name: dst_file_name,mode: "wb");
110 try
111 {
112 char buffer[data_size];
113 my_fread( buffer, size: 1, count: data_size, stream: src );
114 my_fwrite( buffer, size: 1, count: data_size, stream: dst );
115 }
116 catch(
117 boost::exception & x )
118 {
119 if( boost::weak_ptr<FILE> const * f=boost::get_error_info<boost::errinfo_file_handle>(some_exception&: x) )
120 if( boost::shared_ptr<FILE> fs = f->lock() )
121 {
122 if( fs==src )
123 x << boost::errinfo_file_name(src_file_name);
124 else if( fs==dst )
125 x << boost::errinfo_file_name(dst_file_name);
126 }
127 x <<
128 errinfo_src_file_name(src_file_name) <<
129 errinfo_dst_file_name(dst_file_name);
130 throw;
131 }
132 }
133
134void
135dump_copy_info( boost::exception const & x )
136 {
137 if( std::string const * src = boost::get_error_info<errinfo_src_file_name>(some_exception: x) )
138 std::cerr << "Source file name: " << *src << "\n";
139 if( std::string const * dst = boost::get_error_info<errinfo_dst_file_name>(some_exception: x) )
140 std::cerr << "Destination file name: " << *dst << "\n";
141 }
142
143void
144dump_file_info( boost::exception const & x )
145 {
146 if( std::string const * fn = boost::get_error_info<boost::errinfo_file_name>(some_exception: x) )
147 std::cerr << "File name: " << *fn << "\n";
148 }
149
150void
151dump_clib_info( boost::exception const & x )
152 {
153 if( int const * err=boost::get_error_info<boost::errinfo_errno>(some_exception: x) )
154 std::cerr << "OS error: " << *err << "\n";
155 if( char const * const * fn=boost::get_error_info<boost::errinfo_api_function>(some_exception: x) )
156 std::cerr << "Failed function: " << *fn << "\n";
157 }
158
159void
160dump_all_info( boost::exception const & x )
161 {
162 std::cerr << "-------------------------------------------------\n";
163 dump_copy_info(x);
164 dump_file_info(x);
165 dump_clib_info(x);
166 std::cerr << "\nOutput from diagnostic_information():\n";
167 std::cerr << diagnostic_information(e: x);
168 }
169
170int
171main()
172 {
173 try
174 {
175 create_data( file_name: "tmp1.txt" );
176 copy_data( src_file_name: "tmp1.txt", dst_file_name: "tmp2.txt" ); //This should succeed.
177
178 reset_file( file_name: "tmp1.txt" ); //Creates empty file.
179 try
180 {
181 copy_data( src_file_name: "tmp1.txt", dst_file_name: "tmp2.txt" ); //This should fail, tmp1.txt is empty.
182 }
183 catch(
184 read_error & x )
185 {
186 std::cerr << "\nCaught 'read_error' exception.\n";
187 dump_all_info(x);
188 }
189
190 remove( filename: "tmp1.txt" );
191 remove( filename: "tmp2.txt" );
192 try
193 {
194 copy_data( src_file_name: "tmp1.txt", dst_file_name: "tmp2.txt" ); //This should fail, tmp1.txt does not exist.
195 }
196 catch(
197 open_error & x )
198 {
199 std::cerr << "\nCaught 'open_error' exception.\n";
200 dump_all_info(x);
201 }
202 }
203 catch(
204 ... )
205 {
206 std::cerr << "\nCaught unexpected exception!\n";
207 std::cerr << boost::current_exception_diagnostic_information();
208 }
209 }
210

source code of boost/libs/exception/example/example_io.cpp