| // Copyright 2014 The Emscripten Authors. All rights reserved. |
| // Emscripten is available under two separate licenses, the MIT license and the |
| // University of Illinois/NCSA Open Source License. Both these licenses can be |
| // found in the LICENSE file. |
| |
| #include <ios> |
| #include <iostream> |
| #include <sstream> |
| #include <stdexcept> |
| |
| namespace |
| { |
| struct TestEnum |
| { |
| enum type |
| { |
| Zero, |
| One |
| }; |
| }; |
| |
| // An input operator a-la-boost date_time. This input operator will catch |
| // anything and rethrow if the exception mask for the input stream is set to |
| // throw on failure. |
| std::istream& operator>>(std::istream& in, TestEnum::type& value) |
| { |
| try { |
| std::string raw; |
| if (not (in >> raw)) { return in; } |
| if (raw == "Zero") { value = TestEnum::Zero; return in; } |
| if (raw == "One") { value = TestEnum::One; return in; } |
| |
| // The boost input operator uses it's own facet for input which can |
| // throw, so we simulate something failing by just throwing an exception |
| // directly. |
| throw std::exception(); |
| } |
| catch (...) { |
| const std::ios_base::iostate exception_mask = in.exceptions(); |
| if (std::ios_base::failbit & exception_mask) { |
| try { in.setstate(std::ios_base::failbit); } |
| catch(std::ios_base::failure&) {} |
| throw; // rethrow original exception |
| } |
| else { |
| in.setstate(std::ios_base::failbit); |
| } |
| } |
| return in; |
| } |
| } |
| |
| int main() |
| { |
| try { |
| // Show that the input operator works. |
| std::istringstream iss("One"); |
| TestEnum::type value = TestEnum::Zero; |
| |
| // We expect this to work. |
| iss >> value; |
| if (iss.fail()) { |
| std::cout |
| << "Failed to convert 'One' to TestEnum::type... fail" |
| << std::endl; |
| } |
| else { |
| std::cout |
| << "Successfully converted 'One' to TestEnum::type: " << value |
| << "... ok" << std::endl; |
| } |
| } |
| catch (...) { |
| std::cout |
| << "Unknown exception caught converting 'One' to TestEnum... fail" |
| << std::endl; |
| } |
| |
| try { |
| // Show that invalid input set the fail bit on the input stream and no |
| // exception is thrown, since we did not enable them on the stream. |
| std::istringstream iss("Two"); |
| TestEnum::type value = TestEnum::Zero; |
| |
| // We expect this to fail. |
| iss >> value; |
| if (iss.fail()) { |
| std::cout |
| << "Failed to convert 'Two' to TestEnum::type... ok" |
| << std::endl; |
| } |
| else { |
| std::cout |
| << "Successfully converted 'Two' to TestEnum::type: " << value |
| << "... fail" << std::endl; |
| } |
| } |
| catch (...) { |
| std::cout |
| << "Unknown exception caught converting 'Two' to TestEnum... fail" |
| << std::endl; |
| } |
| |
| try { |
| // Show that setting the input stream to throw on failure currently |
| // results in a JS exception being emitted. |
| std::istringstream iss("Three"); |
| TestEnum::type value = TestEnum::Zero; |
| |
| // Tell the stream to throw on failure. |
| iss.exceptions(std::ios_base::failbit); |
| |
| // We expect this to fail. |
| iss >> value; |
| if (iss.fail()) { |
| std::cout |
| << "No exception thrown; Failed to convert 'Three' to TestEnum::type..." |
| "fail" << std::endl; |
| } |
| else { |
| std::cout |
| << "Successfully converted 'Three' to TestEnum::type: " << value |
| << "... fail" << std::endl; |
| } |
| } |
| catch(const std::ios_base::failure& ex) { |
| std::cout << "Caught exception: " << ex.what() << "... ok" << std::endl; |
| } |
| catch (...) { |
| std::cout |
| << "Unknown exception caught converting 'Three' to TestEnum... fail" |
| << std::endl; |
| } |
| |
| return 0; |
| } |
| |