//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc. //Distributed under the Boost Software License, Version 1.0. (See accompanying //file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) //This program simulates errors on copying simple data files. It demonstrates //typical Boost Exception usage. //The output from this program can vary depending on the platform. #include #include #include #include #include #include #include #include #include #include #include #include typedef boost::error_info errinfo_src_file_name; typedef boost::error_info errinfo_dst_file_name; char const data[] = "example"; size_t const data_size = sizeof(data); class error: //Base for all exception objects we throw. public virtual std::exception, public virtual boost::exception { public: char const * what() const BOOST_NOEXCEPT_OR_NOTHROW { return "example_io error"; } protected: ~error() BOOST_NOEXCEPT_OR_NOTHROW { } }; struct open_error: virtual error { }; struct read_error: virtual error { }; struct write_error: virtual error { }; struct fopen_error: virtual open_error { }; struct fread_error: virtual read_error { }; struct fwrite_error: virtual write_error { }; boost::shared_ptr my_fopen( char const * name, char const * mode ) { if( FILE * f = ::fopen(name,mode) ) return boost::shared_ptr(f,fclose); else BOOST_THROW_EXCEPTION(fopen_error() << boost::errinfo_errno (errno) << boost::errinfo_file_name(name) << boost::errinfo_file_open_mode(mode) << boost::errinfo_api_function("fopen")); } void my_fread( void * buffer, size_t size, size_t count, boost::shared_ptr const & stream ) { assert(stream); if( count!=fread(buffer,size,count,stream.get()) || ferror(stream.get()) ) BOOST_THROW_EXCEPTION(fread_error() << boost::errinfo_api_function("fread") << boost::errinfo_errno(errno) << boost::errinfo_file_handle(boost::weak_ptr(stream))); } void my_fwrite( void const * buffer, size_t size, size_t count, boost::shared_ptr const & stream ) { assert(stream); if( count!=fwrite(buffer,size,count,stream.get()) || ferror(stream.get()) ) BOOST_THROW_EXCEPTION(fwrite_error() << boost::errinfo_api_function("fwrite") << boost::errinfo_errno(errno) << boost::errinfo_file_handle(boost::weak_ptr(stream))); } void reset_file( char const * file_name ) { (void) my_fopen(file_name,"wb"); } void create_data( char const * file_name ) { boost::shared_ptr f = my_fopen(file_name,"wb"); my_fwrite( data, 1, data_size, f ); } void copy_data( char const * src_file_name, char const * dst_file_name ) { boost::shared_ptr src = my_fopen(src_file_name,"rb"); boost::shared_ptr dst = my_fopen(dst_file_name,"wb"); try { char buffer[data_size]; my_fread( buffer, 1, data_size, src ); my_fwrite( buffer, 1, data_size, dst ); } catch( boost::exception & x ) { if( boost::weak_ptr const * f=boost::get_error_info(x) ) if( boost::shared_ptr fs = f->lock() ) { if( fs==src ) x << boost::errinfo_file_name(src_file_name); else if( fs==dst ) x << boost::errinfo_file_name(dst_file_name); } x << errinfo_src_file_name(src_file_name) << errinfo_dst_file_name(dst_file_name); throw; } } void dump_copy_info( boost::exception const & x ) { if( std::string const * src = boost::get_error_info(x) ) std::cerr << "Source file name: " << *src << "\n"; if( std::string const * dst = boost::get_error_info(x) ) std::cerr << "Destination file name: " << *dst << "\n"; } void dump_file_info( boost::exception const & x ) { if( std::string const * fn = boost::get_error_info(x) ) std::cerr << "File name: " << *fn << "\n"; } void dump_clib_info( boost::exception const & x ) { if( int const * err=boost::get_error_info(x) ) std::cerr << "OS error: " << *err << "\n"; if( char const * const * fn=boost::get_error_info(x) ) std::cerr << "Failed function: " << *fn << "\n"; } void dump_all_info( boost::exception const & x ) { std::cerr << "-------------------------------------------------\n"; dump_copy_info(x); dump_file_info(x); dump_clib_info(x); std::cerr << "\nOutput from diagnostic_information():\n"; std::cerr << diagnostic_information(x); } int main() { try { create_data( "tmp1.txt" ); copy_data( "tmp1.txt", "tmp2.txt" ); //This should succeed. reset_file( "tmp1.txt" ); //Creates empty file. try { copy_data( "tmp1.txt", "tmp2.txt" ); //This should fail, tmp1.txt is empty. } catch( read_error & x ) { std::cerr << "\nCaught 'read_error' exception.\n"; dump_all_info(x); } remove( "tmp1.txt" ); remove( "tmp2.txt" ); try { copy_data( "tmp1.txt", "tmp2.txt" ); //This should fail, tmp1.txt does not exist. } catch( open_error & x ) { std::cerr << "\nCaught 'open_error' exception.\n"; dump_all_info(x); } } catch( ... ) { std::cerr << "\nCaught unexpected exception!\n"; std::cerr << boost::current_exception_diagnostic_information(); } }