aboutsummaryrefslogtreecommitdiff
path: root/butl/diagnostics
diff options
context:
space:
mode:
Diffstat (limited to 'butl/diagnostics')
-rw-r--r--butl/diagnostics226
1 files changed, 0 insertions, 226 deletions
diff --git a/butl/diagnostics b/butl/diagnostics
deleted file mode 100644
index 18008d5..0000000
--- a/butl/diagnostics
+++ /dev/null
@@ -1,226 +0,0 @@
-// file : butl/diagnostics -*- C++ -*-
-// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd
-// license : MIT; see accompanying LICENSE file
-
-#ifndef BUTL_DIAGNOSTICS
-#define BUTL_DIAGNOSTICS
-
-#include <cassert>
-#include <ostream>
-#include <sstream>
-#include <utility> // move(), forward()
-#include <butl/ft/exception> // uncaught_exceptions
-#include <exception> // uncaught_exception(s)()
-
-#include <butl/export>
-#include <butl/utility>
-
-namespace butl
-{
- // Diagnostic facility base infrastructure.
- //
-
- // Diagnostics destination stream (std::cerr by default). Note that its
- // modification is not MT-safe. Also note that concurrent writing to the
- // stream from multiple threads can result in interleaved characters. To
- // prevent this an object of diag_lock type (see below) must be created prior
- // to write operation.
- //
- LIBBUTL_EXPORT extern std::ostream* diag_stream;
-
- // Acquire the diagnostics exclusive access mutex in ctor, release in dtor.
- // An object of the type must be created prior to writing to diag_stream (see
- // above).
- //
- struct LIBBUTL_EXPORT diag_lock
- {
- diag_lock ();
- ~diag_lock ();
- };
-
- struct diag_record;
- template <typename> struct diag_prologue;
- template <typename> struct diag_mark;
-
- using diag_epilogue = void (const diag_record&);
-
- struct LIBBUTL_EXPORT diag_record
- {
- template <typename T>
- friend const diag_record&
- operator<< (const diag_record& r, const T& x)
- {
- r.os << x;
- return r;
- }
-
- diag_record ()
- :
-#ifdef __cpp_lib_uncaught_exceptions
- uncaught_ (std::uncaught_exceptions ()),
-#endif
- empty_ (true),
- epilogue_ (nullptr) {}
-
- template <typename B>
- explicit
- diag_record (const diag_prologue<B>& p): diag_record () { *this << p;}
-
- template <typename B>
- explicit
- diag_record (const diag_mark<B>& m): diag_record () { *this << m;}
-
- ~diag_record () noexcept (false);
-
- bool
- empty () const {return empty_;}
-
- bool
- full () const {return !empty_;}
-
- void
- flush () const;
-
- void
- append (const char* indent, diag_epilogue* e) const
- {
- // Ignore subsequent epilogues (e.g., from nested marks, etc).
- //
- if (empty_)
- {
- epilogue_ = e;
- empty_ = false;
- }
- else if (indent != nullptr)
- os << indent;
- }
-
- // Move constructible-only type.
- //
- // Older versions of libstdc++ don't have the ostringstream move support
- // and accuratly detecting its version is non-trivial. So we always use
- // the pessimized implementation with libstdc++. Luckily, GCC doesn't seem
- // to be needing move due to copy/move elision.
- //
-#ifdef __GLIBCXX__
- diag_record (diag_record&&);
-#else
- diag_record (diag_record&& r)
- :
-#ifdef __cpp_lib_uncaught_exceptions
- uncaught_ (r.uncaught_),
-#endif
- empty_ (r.empty_),
- epilogue_ (r.epilogue_),
- os (std::move (r.os))
- {
- if (!empty_)
- {
- r.empty_ = true;
- r.epilogue_ = nullptr;
- }
- }
-#endif
-
- diag_record& operator= (diag_record&&) = delete;
-
- diag_record (const diag_record&) = delete;
- diag_record& operator= (const diag_record&) = delete;
-
- protected:
-#ifdef __cpp_lib_uncaught_exceptions
- const int uncaught_;
-#endif
- mutable bool empty_;
- mutable diag_epilogue* epilogue_;
-
- public:
- mutable std::ostringstream os;
- };
-
- template <typename B>
- struct diag_prologue: B
- {
- diag_prologue (const char* i = "\n ", diag_epilogue* e = nullptr)
- : B (), indent_ (i), epilogue_ (e) {}
-
- template <typename... A>
- diag_prologue (A&&... a)
- : B (std::forward<A> (a)...), indent_ ("\n "), epilogue_ (nullptr) {}
-
- template <typename... A>
- diag_prologue (diag_epilogue* e, A&&... a)
- : B (std::forward<A> (a)...), indent_ ("\n "), epilogue_ (e) {}
-
- template <typename... A>
- diag_prologue (const char* i, diag_epilogue* e, A&&... a)
- : B (std::forward<A> (a)...), indent_ (i), epilogue_ (e) {}
-
- template <typename T>
- diag_record
- operator<< (const T& x) const
- {
- diag_record r;
- r.append (indent_, epilogue_);
- B::operator() (r);
- r << x;
- return r;
- }
-
- friend const diag_record&
- operator<< (const diag_record& r, const diag_prologue& p)
- {
- r.append (p.indent_, p.epilogue_);
- p (r);
- return r;
- }
-
- private:
- const char* indent_;
- diag_epilogue* epilogue_;
- };
-
- template <typename B>
- struct diag_mark: B
- {
- diag_mark (): B () {}
-
- template <typename... A>
- diag_mark (A&&... a): B (std::forward<A> (a)...) {}
-
- template <typename T>
- diag_record
- operator<< (const T& x) const
- {
- return B::operator() () << x;
- }
-
- friend const diag_record&
- operator<< (const diag_record& r, const diag_mark& m)
- {
- return r << m ();
- }
- };
-
- template <typename B>
- struct diag_noreturn_end: B
- {
- diag_noreturn_end (): B () {}
-
- template <typename... A>
- diag_noreturn_end (A&&... a): B (std::forward<A> (a)...) {}
-
- [[noreturn]] friend void
- operator<< (const diag_record& r, const diag_noreturn_end& e)
- {
- // We said that we never return which means this end mark cannot be used
- // to "maybe not return". And not returning without any diagnostics is
- // probably a mistake.
- //
- assert (r.full ());
- e.B::operator() (r);
- }
- };
-}
-
-#endif // BUTL_DIAGNOSTICS