blob: d971a3f0dea28d4f79530820ce0573d48fe24abb (
plain)
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
|
// file : butl/utility.cxx -*- C++ -*-
// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd
// license : MIT; see accompanying LICENSE file
#include <ostream>
#include <butl/utility>
namespace butl
{
#ifndef BUTL_CXX17_UNCAUGHT_EXCEPTIONS
#ifdef BUTL_CXX11_THREAD_LOCAL
thread_local
#else
__thread
#endif
bool exception_unwinding_dtor_ = false;
#ifdef _WIN32
bool&
exception_unwinding_dtor () {return exception_unwinding_dtor_;}
#endif
#endif
}
namespace std
{
using namespace butl;
ostream&
operator<< (ostream& o, const exception& e)
{
const char* d (e.what ());
const char* s (d);
// Strip the leading junk (colons and spaces).
//
// Note that error descriptions for ios_base::failure exceptions thrown by
// fdstream can have the ': ' prefix for libstdc++ (read more in comment
// for throw_ios_failure()).
//
for (; *s == ' ' || *s == ':'; ++s) ;
// Strip the trailing junk (periods, spaces, newlines).
//
// Note that msvcrt adds some junk like this:
//
// Invalid data.\r\n
//
size_t n (string::traits_type::length (s));
for (; n > 0; --n)
{
switch (s[n-1])
{
case '\r':
case '\n':
case '.':
case ' ': continue;
}
break;
}
// Lower-case the first letter if the beginning looks like a word (the
// second character is the lower-case letter or space).
//
char c;
bool lc (n > 0 && alpha (c = s[0]) && c == ucase (c) &&
(n == 1 || (alpha (c = s[1]) && c == lcase (c)) || c == ' '));
// Print the description as is if no adjustment is required.
//
if (!lc && s == d && s[n] == '\0')
o << d;
else
{
// We need to produce the resulting description and then write it
// with a single formatted output operation.
//
string r (s, n);
if (lc)
r[0] = lcase (r[0]);
o << r;
}
return o;
}
}
|