File: test_exceptions_rethrow.cpp

package info (click to toggle)
emscripten 2.0.12~dfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 108,440 kB
  • sloc: ansic: 510,324; cpp: 384,763; javascript: 84,341; python: 51,362; sh: 50,019; pascal: 4,159; makefile: 3,409; asm: 2,150; lisp: 1,869; ruby: 488; cs: 142
file content (99 lines) | stat: -rw-r--r-- 2,766 bytes parent folder | download | duplicates (4)
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
// 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.
      std::ios_base::failure failz("<input failure>");
      std::cout
        << "Throwing std::ios_base::failure: |" << failz.what() << "|..."
        << std::endl;
      throw failz;
    }
    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 setting the input stream to throw on failure does not
    // preserve the exception type.
    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) {
    // This is what we expect to catch.
    std::cout
      << "Caught std::ios_base::failure: |" << ex.what() << "|... ok"
      << std::endl;
  }
  catch(const std::exception& ex) {
    std::cout << "Caught exception: " << ex.what() << "... fail" << std::endl;
  }
  catch (...) {
    // This is what is actually caught.
    std::cout
      << "Unknown exception caught converting 'Three' to TestEnum... fail"
      << std::endl;
  }

  return 0;
}