1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
|
// 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;
}
|