]>
Commit | Line | Data |
---|---|---|
bbc27441 | 1 | /* |
f70aedc4 | 2 | * Copyright (C) 1996-2021 The Squid Software Foundation and contributors |
bbc27441 AJ |
3 | * |
4 | * Squid software is distributed under GPLv2+ license and includes | |
5 | * contributions from numerous individuals and organizations. | |
6 | * Please see the COPYING and CONTRIBUTORS files for details. | |
7 | */ | |
8 | ||
582c2af2 | 9 | #include "squid.h" |
3d93a84d | 10 | #include "base/TextException.h" |
e99fa721 | 11 | #include "sbuf/SBuf.h" |
774c051c | 12 | |
ebaabe74 AR |
13 | #include <iostream> |
14 | #include <sstream> | |
15 | #include <unordered_map> | |
77442705 | 16 | |
ebaabe74 AR |
17 | /// a standard CoW string; avoids noise and circular dependencies of SBuf |
18 | typedef std::runtime_error WhatString; | |
77442705 | 19 | |
ebaabe74 AR |
20 | /// a collection of strings indexed by pointers to their creator objects |
21 | typedef std::unordered_multimap<const void*, WhatString> WhatStrings; | |
22 | ||
23 | /// requested what() strings of alive TextException objects | |
24 | static WhatStrings *WhatStrings_ = nullptr; | |
774c051c | 25 | |
ebaabe74 AR |
26 | TextException::TextException(SBuf message, const SourceLocation &location): |
27 | TextException(message.c_str(), location) | |
e99fa721 EB |
28 | {} |
29 | ||
0a8bbeeb | 30 | TextException::~TextException() throw() |
774c051c | 31 | { |
ebaabe74 AR |
32 | if (WhatStrings_) |
33 | WhatStrings_->erase(this); // there only if what() has been called | |
77442705 AJ |
34 | } |
35 | ||
ebaabe74 AR |
36 | std::ostream & |
37 | TextException::print(std::ostream &os) const | |
77442705 | 38 | { |
ccfbe8f4 | 39 | os << std::runtime_error::what() << |
77b1029d | 40 | Debug::Extra << "exception location: " << where; |
ccfbe8f4 | 41 | // TODO: ...error_detail: " << (ERR_DETAIL_EXCEPTION_START+id()); |
ebaabe74 | 42 | return os; |
774c051c | 43 | } |
44 | ||
ebaabe74 AR |
45 | const char * |
46 | TextException::what() const throw() | |
0a8bbeeb | 47 | { |
ebaabe74 AR |
48 | std::ostringstream os; |
49 | print(os); | |
50 | const WhatString result(os.str()); | |
0a8bbeeb | 51 | |
ebaabe74 AR |
52 | // extend result.c_str() lifetime to this object lifetime |
53 | if (!WhatStrings_) | |
54 | WhatStrings_ = new WhatStrings; | |
55 | // *this could change, but we must preserve old results for they may be used | |
56 | WhatStrings_->emplace(std::make_pair(this, result)); | |
64b66b76 | 57 | |
ebaabe74 | 58 | return result.what(); |
64b66b76 CT |
59 | } |
60 | ||
83b053a0 CT |
61 | std::ostream & |
62 | operator <<(std::ostream &os, const TextException &ex) | |
63 | { | |
64 | ex.print(os); | |
65 | return os; | |
66 | } | |
67 | ||
ebaabe74 AR |
68 | std::ostream & |
69 | CurrentException(std::ostream &os) | |
774c051c | 70 | { |
ebaabe74 AR |
71 | if (std::current_exception()) { |
72 | try { | |
73 | throw; // re-throw to recognize the exception type | |
74 | } | |
83b053a0 CT |
75 | catch (const TextException &ex) { |
76 | os << ex; // optimization: this is a lot cheaper than what() below | |
77 | } | |
ebaabe74 AR |
78 | catch (const std::exception &ex) { |
79 | os << ex.what(); | |
80 | } | |
81 | catch (...) { | |
82 | os << "[unknown exception type]"; | |
83 | } | |
774c051c | 84 | } else { |
ebaabe74 | 85 | os << "[no active exception]"; |
774c051c | 86 | } |
ebaabe74 | 87 | return os; |
774c051c | 88 | } |
f53969cc | 89 |