example_io.cpp 6.3 KB

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