• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
24 typedef boost::error_info<struct tag_file_name_src,std::string> errinfo_src_file_name;
25 typedef boost::error_info<struct tag_file_name_dst,std::string> errinfo_dst_file_name;
26 
27 char const data[] = "example";
28 size_t const data_size = sizeof(data);
29 
30 class
31 error: //Base for all exception objects we throw.
32     public virtual std::exception,
33     public virtual boost::exception
34     {
35     public:
36 
37     char const *
what() const38     what() const BOOST_NOEXCEPT_OR_NOTHROW
39         {
40         return "example_io error";
41         }
42 
43     protected:
44 
~error()45     ~error() BOOST_NOEXCEPT_OR_NOTHROW
46         {
47         }
48     };
49 
50 struct open_error: virtual error { };
51 struct read_error: virtual error { };
52 struct write_error: virtual error { };
53 struct fopen_error: virtual open_error { };
54 struct fread_error: virtual read_error { };
55 struct fwrite_error: virtual write_error { };
56 
57 boost::shared_ptr<FILE>
my_fopen(char const * name,char const * mode)58 my_fopen( char const * name, char const * mode )
59     {
60     if( FILE * f = ::fopen(name,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 
70 void
my_fread(void * buffer,size_t size,size_t count,boost::shared_ptr<FILE> const & stream)71 my_fread( void * buffer, size_t size, size_t count, boost::shared_ptr<FILE> const & stream )
72     {
73     assert(stream);
74     if( count!=fread(buffer,size,count,stream.get()) || ferror(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 
81 void
my_fwrite(void const * buffer,size_t size,size_t count,boost::shared_ptr<FILE> const & stream)82 my_fwrite( void const * buffer, size_t size, size_t count, boost::shared_ptr<FILE> const & stream )
83     {
84     assert(stream);
85     if( count!=fwrite(buffer,size,count,stream.get()) || ferror(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 
92 void
reset_file(char const * file_name)93 reset_file( char const * file_name )
94     {
95     (void) my_fopen(file_name,"wb");
96     }
97 
98 void
create_data(char const * file_name)99 create_data( char const * file_name )
100     {
101     boost::shared_ptr<FILE> f = my_fopen(file_name,"wb");
102     my_fwrite( data, 1, data_size, f );
103     }
104 
105 void
copy_data(char const * src_file_name,char const * dst_file_name)106 copy_data( char const * src_file_name, char const * dst_file_name )
107     {
108     boost::shared_ptr<FILE> src = my_fopen(src_file_name,"rb");
109     boost::shared_ptr<FILE> dst = my_fopen(dst_file_name,"wb");
110     try
111         {
112         char buffer[data_size];
113         my_fread( buffer, 1, data_size, src );
114         my_fwrite( buffer, 1, data_size, 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>(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 
134 void
dump_copy_info(boost::exception const & x)135 dump_copy_info( boost::exception const & x )
136     {
137     if( std::string const * src = boost::get_error_info<errinfo_src_file_name>(x) )
138         std::cerr << "Source file name: " << *src << "\n";
139     if( std::string const * dst = boost::get_error_info<errinfo_dst_file_name>(x) )
140         std::cerr << "Destination file name: " << *dst << "\n";
141     }
142 
143 void
dump_file_info(boost::exception const & x)144 dump_file_info( boost::exception const & x )
145     {
146     if( std::string const * fn = boost::get_error_info<boost::errinfo_file_name>(x) )
147         std::cerr << "File name: " << *fn << "\n";
148     }
149 
150 void
dump_clib_info(boost::exception const & x)151 dump_clib_info( boost::exception const & x )
152     {
153     if( int const * err=boost::get_error_info<boost::errinfo_errno>(x) )
154         std::cerr << "OS error: " << *err << "\n";
155     if( char const * const * fn=boost::get_error_info<boost::errinfo_api_function>(x) )
156         std::cerr << "Failed function: " << *fn << "\n";
157     }
158 
159 void
dump_all_info(boost::exception const & x)160 dump_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(x);
168     }
169 
170 int
main()171 main()
172     {
173     try
174         {
175         create_data( "tmp1.txt" );
176         copy_data( "tmp1.txt", "tmp2.txt" ); //This should succeed.
177 
178         reset_file( "tmp1.txt" ); //Creates empty file.
179         try
180             {
181             copy_data( "tmp1.txt", "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( "tmp1.txt" );
191         remove( "tmp2.txt" );
192         try
193             {
194             copy_data( "tmp1.txt", "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